这可能不会阻止winForm使用WaitHandle.WaitAll(waitHandles)但只是设置另一个线程,当从WaitHandle.WaitAll获取complate信号时将触发吗?
答案 0 :(得分:3)
我不会使用WaitHandle.WaitAll
。这种方法存在一些问题。
WaitHandle
实例的模式。相反,我想在等待多个事件时使用CountdownEvent
类。现在,您将遇到的问题是它仍然需要您在某个线程上调用Wait
,这正是您要避免的。避免进行阻塞调用的标准机制是使用ThreadPool.RegisterWaitForSingleObject
方法。但是,遗憾的是,WaitHandle
和CountdownEvent
不会从该类继承。
解决方案是创建自己的CountdownWaitHandle
类,可以在ThreadPool.RegisterWaitForSingleObject
方法中使用。此方法将允许您指定一个回调委托,该委托将在WaitHandle
发出信号后执行。
这是CountdownWaitHandle
类的最基本的实现。你必须自己添加所有必要的硬化代码,但这会让你开始。
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
将进入信号状态。因此,您不必在多个Set
个实例上调用WaitHandle
并使用WaitHandle.WaitAll
进行阻止,而是在此一个实例上调用Signal
,然后通过调用WaitOne
来阻止。同样,您可以使用TheadPool.RegisterWaitForSingleObject
推迟对线程池的阻塞调用,WaitHandle
将在{{1}}发出信号时调用回调。
答案 1 :(得分:0)
您可以在后台线程中调用WaitAll
,然后调用BeginInvoke
以返回UI线程。
答案 2 :(得分:0)
看看ManualResetEvent
。使用它可以在线程完成时设置事件,任何其他线程都可以等待此事件,或检查它是否处于信号状态。
ManualResetEvent ev = new ManualReserEvent();
while(Users["user428547"].AcceptanceRate == 0)
{
// this might take a long time
};
ev.Set(); // done, he accepted an answer.
答案 3 :(得分:0)
也许您可以自己启动另一个帖子,并在该线程上自己调用WaitHandle.WaitAll
?如果你没有开始太多其他线程,这应该可以正常工作。