2010-11-21 31 views
2

这可能不会阻止使用WaitHandle.WaitAll(waitHandles)的winForm,但只需设置另一个线程,它将从WaitHandle.WaitAll获取complate信号时触发?C#线程,WaitHandle.WaitAll

+6

你应该接受你的问题的答案。 – SLaks 2010-11-21 18:54:49

回答

3

我不会使用WaitHandle.WaitAll。这种方法存在一些问题。

  • 有64个手柄限制。
  • 它不能在STA线程上使用。
  • 它促进了模式,这取决于创建明显消耗资源的多个WaitHandle实例。

相反,我通常在我想等待多个事件时使用CountdownEvent类。现在,你将遇到的问题是它仍然要求你在某个线程上调用Wait,这正是你想要避免的。避免进行阻塞呼叫的标准机制是使用ThreadPool.RegisterWaitForSingleObject方法。但是,不幸的是,这需要WaitHandleCountdownEvent不会从该类继承。

解决的方法是创建您自己的CountdownWaitHandle类,该类可以在ThreadPool.RegisterWaitForSingleObject方法中使用。这种方法将允许您指定一个WaitHandle被发送信号后执行的回调委托。

这是CountdownWaitHandle类的最基本的实现。你将不得不自己添加所有必要的代码,但这会让你开始。

​​

的这里的想法是,而不是使用许多不同的WaitHandle情况下,你使用一个CountdownWaitHandle实例。用期望的计数初始化实例,然后调用Signal减少计数。一旦计数变为零,WaitHandle将进入信号状态。因此,您不必在多个WaitHandle实例上调用Set,并使用WaitHandle.WaitAll阻止,您现在在此实例上调用Signal,并通过调用WaitOne来阻止。再次,您可以通过使用TheadPool.RegisterWaitForSingleObject来阻止对线程池的阻止调用,当WaitHandle被发信号时它将调用回调。

0

你可以在后台线程中调用WaitAll,然后调用BeginInvoke返回到UI线程。

+0

你可以更具体吗? – kosnkov 2010-11-21 19:24:35

0

看一看ManualResetEvent。使用它你可以在线程完成时设置事件,任何其他线程都可以等待这个事件,或者检查它是否处于信号状态。

ManualResetEvent ev = new ManualReserEvent(); 
while(Users["user428547"].AcceptanceRate == 0) 
{ 
    // this might take a long time 
}; 
ev.Set(); // done, he accepted an answer. 
0

也许你可以启动另一个线程自己,并呼吁WaitHandle.WaitAll自己上线?如果你没有启动太多的其他线程,这应该工作得很好。

+0

没有COS然后我得到WaitAll STA支持多个句柄线程不支持 – kosnkov 2010-11-21 20:31:21

+0

你不能让新线程成为MTA线程吗? MSDN社交似乎在这里有关于此的讨论:http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/eefc0160-987c-47e1-a41b-bbae96726ec4/ – dsolimano 2010-11-21 22:51:24