Reputation: 93287
If you have one main thread that starts two other threads. what is the cleanest way to make the primary thread wait for the two other threads?
I could use bgndworker and sleep spinner that checks for both the bgnd workers's IsBusy, but I would think there's a better way.
EDIT Some more requirements:
Upvotes: 3
Views: 12194
Reputation: 8448
You can't wait for finish and have GUI usable. The best approach for this is to spawn threads and use events to communicate with GUI. Remember, that in the event handler you cannot modify control. Rather that doing it directly, use Invoke method.
Upvotes: 1
Reputation: 1062520
See the answers on this thread. I like this option ;-p
Forker p = new Forker();
p.Fork(delegate { DoSomeWork(); });
p.Fork(delegate { DoSomeOtherWork(); });
p.Join();
Re returning values / reporting exceptions - just have each fork do that as a callback at the end of the logic... (you can use captured variables to pass state into both the forks, including a shared logger etc).
Upvotes: 5
Reputation: 1499740
In addition to the other answers... one alternative to "start two threads and wait for both to finish" is "start one thread and do one job yourself, then wait for the other thread to finish".
Of course, if you want to start two jobs, do some more work on the main thread and then wait for the two other threads to finish, that doesn't work so well.
EDIT: If the main thread is a UI thread, you shouldn't be blocking on the other threads finishing - you should (IMO) get them to call back to the main thread when they've finished. That way you'll still have a responsive UI while they're executing.
Upvotes: 1
Reputation: 93424
WaitHandle.WaitAny is your friend. It lets you wait on multiple threads or other kinds of objects to be signaled.
http://msdn.microsoft.com/en-us/library/tdykks7z.aspx
EDIT:
Actually, WaitHandle.WaitAll is what you want, not WaitAny.
http://msdn.microsoft.com/en-us/library/system.threading.waithandle.waitall.aspx
EDIT:
The Join method some mention is ok, but one drawback is that it's not an completely atomic operation. This may or may not be important to you, though.
Upvotes: 0
Reputation: 10764
Quick example using Thread.Join();
Thread t1 = new Thread(new ThreadStart(delegate()
{
System.Threading.Thread.Sleep(2000);
}));
Thread t2 = new Thread(new ThreadStart(delegate()
{
System.Threading.Thread.Sleep(4000);
}));
t1.Start();
t2.Start();
t1.Join();
t2.Join();
EDIT Another 3example using Wait Handles:
ManualResetEvent[] waitHandles = new ManualResetEvent[]{
new ManualResetEvent(false),
new ManualResetEvent(false)
};
Thread t1 = new Thread(new ParameterizedThreadStart(delegate(object state)
{
ManualResetEvent handle = (ManualResetEvent)state;
System.Threading.Thread.Sleep(2000);
handle.Set();
}));
Thread t2 = new Thread(new ParameterizedThreadStart(delegate(object state)
{
ManualResetEvent handle = (ManualResetEvent)state;
System.Threading.Thread.Sleep(4000);
handle.Set();
}));
t1.Start(waitHandles[0]);
t2.Start(waitHandles[1]);
WaitHandle.WaitAll(waitHandles);
Console.WriteLine("Finished");
Upvotes: 10