Reputation: 5911
Is that possible not not block winForm using WaitHandle.WaitAll(waitHandles) but just set another thread which will fire when get complate signal from WaitHandle.WaitAll?
Upvotes: 2
Views: 4203
Reputation: 48949
I would not use WaitHandle.WaitAll
. There are a couple of problems with this approach.
WaitHandle
instances which obviously consume resource.Instead, I typically use the CountdownEvent
class when I want to wait on multiple events. Now, the problem you will have with that is that it still requires you to call Wait
on some thread which is exactly what you are trying to avoid. The standard mechanism to avoid making a blocking call is to use the ThreadPool.RegisterWaitForSingleObject
method. But, unfortunately that takes a WaitHandle
and CountdownEvent
does not inherit from that class.
The solution is to create your own CountdownWaitHandle
class that can be used in the ThreadPool.RegisterWaitForSingleObject
method. This approach will allow you to specify a callback delegate that will be executed once the WaitHandle
is signaled.
Here is the most basic implemenation for the CountdownWaitHandle
class. You will have to add all of the necessary harding code yourself, but this will get you started.
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();
}
}
The idea here is that instead of using many different WaitHandle
instances you use a single CountdownWaitHandle
instance. Initialize the instance with the desired count and then call Signal
to decrement the count. Once the count gets to zero the WaitHandle
will go into the signaled state. So instead of calling Set
on multiple WaitHandle
instances and blocking with WaitHandle.WaitAll
you now call Signal
on this one instance and block by calling WaitOne
. And again, you can push off the blocking call to the thread pool by using TheadPool.RegisterWaitForSingleObject
which will invoke a callback when the WaitHandle
is signaled.
Upvotes: 3
Reputation: 8986
Perhaps you could start another thread yourself, and call WaitHandle.WaitAll
yourself on that thread? If you are not starting too many other threads, this should work fine.
Upvotes: 0
Reputation: 38825
Have a look at ManualResetEvent
. Using this you can set the event when your thread has finished, and any other thread can either wait on this event, or check to see if it is in the signalled state.
ManualResetEvent ev = new ManualReserEvent();
while(Users["user428547"].AcceptanceRate == 0)
{
// this might take a long time
};
ev.Set(); // done, he accepted an answer.
Upvotes: 0
Reputation: 887225
You can call WaitAll
in a background thread, then call BeginInvoke
to move back to the UI thread.
Upvotes: 0