2010-06-30 78 views
2

我试图绕过的wait64句柄限制是.NET 3.5的规定线程池 - 为WaitAll 64句柄限制

我已经看到了这个线程:Workaround for the WaitHandle.WaitAll 64 handle limit?

所以我了解大致的构想,但我有困难因为我没有使用一个委托,而是

我基本上是工作的这个例子: http://msdn.microsoft.com/en-us/library/3dasc8as%28VS.80%29.aspx

此链接http://www.switchonthecode.com/tutorials/csharp-tutorial-using-the-threadpool 是相似的,但同样保持任务跟踪的int变量是一个成员变量。

在上面的例子中,我会传递threadCount整数吗? 作为对象在回调方法中传递它吗?我认为我遇到了回调方法和参考传递的问题。

谢谢斯蒂芬,

该链接是不完全清楚的我。

让我后我的代码,以帮助自己澄清:

for (int flows = 0; flows < NumFlows; flows++) 
{ 
ResetEvents[flows] = new ManualResetEvent(false); 
ICalculator calculator = new NewtonRaphson(Perturbations); 
Calculators[flows] = calculator; 
ThreadPool.QueueUserWorkItem(calculator.ThreadPoolCallback, flows); 
} 
resetEvent.WaitOne(); 

我会在哪里掠过我的THREADCOUNT变量。我认为它需要在calculator.ThreadPoolCallback中递减?

+0

什么是numTask整数? – 2010-06-30 19:22:05

+0

对不起,我相信我的意思是来自第一个链接的“threadCount”。 – bearrito 2010-06-30 19:31:45

+1

次要技术问题:64句柄限制是由Win32 API而不是.NET 3.5强加的。所以,Windows上的每个程序都有相同的限制。 – 2010-06-30 19:34:17

回答

0

匿名方法可能是最简单的:

int threadCount = 0; 
for (int flows = 0; flows < NumFlows; flows++) 
{ 
    ICalculator calculator = new NewtonRaphson(Perturbations); 
    Calculators[flows] = calculator; 

    // We're about to queue a new piece of work: 
    // make a note of the fact a new work item is starting 
    Interlocked.Increment(ref threadCount); 
    ThreadPool.QueueUserWorkItem(
     delegate 
     { 
      calculator.ThreadPoolCallback(flows); 

      // We've finished this piece of work... 
      if (Interlocked.Decrement(ref threadCount) == 0) 
      { 
       // ...and we're the last one. 
       // Signal back to the main thread. 
       resetEvent.Set(); 
      } 
     }, null); 
} 
resetEvent.WaitOne(); 
+0

如果你看看提供的链接,你可以看到我试图避免使用匿名方法。 – bearrito 2010-07-02 18:04:08

+0

我不明白你为什么要避免匿名方法 - 你的目标是.NET 1.0或1.1运行时? – 2010-07-02 18:26:12

+0

这里有一个非常微妙的错误。 'WaitOne'和'Interlocked.Decrement'将会竞争导致'WaitOne'返回太早,如果最后一个工作项已经排队*和*在循环的下一次迭代有机会'Interlocked.Increment'之前完成。 – 2010-10-01 17:20:39

1

你不应该使用多个等待句柄等待在ThreadPool多个工作项目的完成。它不仅不可扩展,而且最终还会碰到WaitHandle.WaitAll方法施加的64个句柄限制(正如您已经完成的那样)。在这种情况下使用的正确模式是计数等待句柄。有一个可用的Reactive Extensions下载的.NET 3.5通过CountdownEvent类。

var finished = new CountdownEvent(1); 
for (int flows = 0; flows < NumFlows; flows++) 
{ 
    finished.AddCount(); 
    ICalculator calculator = new NewtonRaphson(Perturbations); 
    Calculators[flows] = calculator; 
    ThreadPool.QueueUserWorkItem(
    (state) => 
    { 
     try 
     { 
     calculator.ThreadPoolCallback(state); 
     } 
     finally 
     { 
     finished.Signal(); 
     } 
    }, flows); 
} 
finished.Signal(); 
finished.Wait();