组合等待句柄?

4
这里有一个比较有趣的问题。我有一个类,负责将多个处理操作复用到固定数量的线程上。典型情况是生产者/消费者问题,其中每个操作由WaitHandle(在这种情况下,是跟踪队列中有多少项的信号量)和要调用的委托组成。
例如,如果我有两个生产者(A和B),它们将项目生产到两个不同的队列中。我不会为每个生产者创建两个消费者线程(A1、A2、B1、B2),而是将这四个“线程”复用到两个线程上。这个“复用器”的代码大致如下(稍微简化了一下):
WaitHandle[] waitHandles = new WaitHandle[2];
waitHandles[0] = NumberOfItemsFullInProducerAQueue;
waitHandles[1] = NumberOfItemsFullInProducerBQueue;
while(true)
{
    int index = WaitHandle.WaitAny(waitHandles);
    if(index == 0)
    {
        // handle the item from queue A
    }
    else
    {
        // handle the item from queue B
    }
}

我正试图将这个概念扩展到一个稍微复杂一些的例子上,在这个例子中,一个操作可能需要多个等待句柄被满足才能执行。我想知道是否有一种 WaitHandle.Combine(waitHandle1, waitHandle2) 的调用方式可以将两个等待句柄合并成一个单独的等待句柄。最终结果将是:

A,B,C,D are waitHandles
E = Combine(A, B)
F = Combine(C, D)
waitHandles = { E, F }

while(true)
{
   int index = WaitHandle.WaitAny(waitHandles);
   if(index == 0)
   {
   }
   else
   {
   }
}

额外的分数?

虽然不是必须的,但如果等待句柄的组合可以相交,那将非常好。例如,像这样:

  A,B,C are waitHandles
  D = Combine(A, B)
  E = Combine(A, C)
  waitHandles = { D, E }
  // same as above from here

感谢您的帮助,SO。

1
额外的点数?那我会等待赏金。 - Hans Passant
我是否在SO社区中犯了什么错误?(这进一步证明了互联网需要讽刺脚本来使这种情况不含糊)... - LorenVS
1
这是不可能的原生支持,因为内核不支持它。你可以尝试通过手动检查信号状态来模拟它,但这对需要副作用的对象在等待满足时不起作用。 - wj32
@wj32 感谢提供的信息。我想我最终可能会实现一种跟踪已成功等待的等待句柄的方法,并使用该信息来决定可以调用哪些操作。 - LorenVS
@wj32:你可以通过让另一个线程等待子集并在条件满足时设置事件来实现这一点。我说“有点像”是因为它不再是原子的,在某些情况下可能会出现问题,但在其他情况下仍然有用。 - Ben Voigt
显示剩余2条评论
1个回答

1
你可能考虑研究一下 .NET 4 TPL 中的新 Barrier 类(作为 Reactive Extensions 的一部分回溯到了 3.5 版本)。它专门为你所描述的场景设计,即需要阻止执行直到多个协作任务达到检查点。你还可以使用 Task 系统创建复杂的继续路径,其中一个 Task 依赖于两个先前完成的任务,取决于第一个 Task 完成,并且如果在任何时候发生异常,则将这些异常聚合并报告到中央位置。

嗯...我想任务可能是解决方案,我可能需要开始做一些转换来更多地使用它们... - LorenVS
1
在链接的MSDN页面中,Barrier类的示例使用了我在MSDN上见过的最丰富多彩的语言。使用“D'oh!”,“Nope--changed my mind”和“hunky-dory”等短语让我认为它是由开发人员而不是技术作家编写的,这增加了人性化的感觉(尽管在更广泛的国际受众中,这样的短语可能会对可读性产生不利影响)。 - Allon Guralnek
@LorenVS,我很喜欢在最近的项目中使用任务。TPL有很多深度,特别是一旦你开始研究依赖任务继续(任务C要求A和B首先成功完成,可能是并行的),协作取消以及它为你管理异常处理的方式。多年来,我已经以不同的方式为不同的项目编写了许多线程管道代码,因此很高兴最终看到这个功能打包在BCL中。 - Dan Bryant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接