有没有可能不使用WaitHandle.WaitAll(waitHandles)阻塞winForm,而只是设置另一个线程,该线程将在从WaitHandle.WaitAll获得complate信号时触发?
发布于 2010-11-25 04:28:55
我不会使用WaitHandle.WaitAll。这种方法有几个问题。
WaitHandle实例的模式,这些实例显然会消耗资源。相反,当我想要等待多个事件时,我通常使用CountdownEvent类。现在,你会遇到的问题是,它仍然需要你在某个线程上调用Wait,而这正是你试图避免的。避免进行阻塞调用的标准机制是使用ThreadPool.RegisterWaitForSingleObject方法。但是,不幸的是,这需要一个WaitHandle,而CountdownEvent不是从该类继承而来的。
解决方案是创建可以在ThreadPool.RegisterWaitForSingleObject方法中使用的您自己的CountdownWaitHandle类。此方法将允许您指定一个回调委托,该委托将在WaitHandle发出信号后执行。
下面是CountdownWaitHandle类的最基本实现。您必须自己添加所有必要的harding代码,但这将帮助您入门。
public class CountdownWaitHandle : WaitHandle
{
private int m_Count = 0;
private ManualResetEvent m_Event = new ManualResetEvent(false);
public CountdownWaitHandle(int initialCount)
{
m_Count = initialCount;
}
public void AddCount()
{
Interlocked.Increment(ref m_Count);
}
public void Signal()
{
if (Interlocked.Decrement(ref m_Count) == 0)
{
m_Event.Set();
}
}
public override bool WaitOne()
{
return m_Event.WaitOne();
}
}这里的想法是使用单个WaitHandle实例,而不是使用许多不同的CountdownWaitHandle实例。使用所需的计数初始化实例,然后调用Signal来递减计数。一旦计数变为零,WaitHandle将进入信号状态。因此,不是在多个WaitHandle实例上调用Set并使用WaitHandle.WaitAll阻塞,而是现在在这个实例上调用Signal,并通过调用WaitOne阻塞。同样,您可以使用TheadPool.RegisterWaitForSingleObject将阻塞调用推送到线程池,它将在WaitHandle发出信号时调用回调。
发布于 2010-11-22 02:55:13
您可以在后台线程中调用WaitAll,然后调用BeginInvoke以移回UI线程。
发布于 2010-11-22 02:56:09
看看ManualResetEvent吧。使用它,您可以在线程完成时设置事件,并且任何其他线程都可以等待此事件,或者检查它是否处于信号状态。
ManualResetEvent ev = new ManualReserEvent();
while(Users["user428547"].AcceptanceRate == 0)
{
// this might take a long time
};
ev.Set(); // done, he accepted an answer.https://stackoverflow.com/questions/4239609
复制相似问题