I can see 5 options available:
1. Thread.Join
As with Mitch's answer. But this will block your UI thread, however you get a Timeout built in for you.
2. Use a WaitHandle
ManualResetEvent
is a WaitHandle
as jrista suggested.
One thing to note is if you want to wait for multiple threads, WaitHandle.WaitAll()
won't work by default, as it needs an MTA thread. You can get around this by marking your Main()
method with MTAThread
- however this blocks your message pump and isn't recommended from what I've read.
3. Fire an event
See this page by Jon Skeet about events and multi-threading, it's possible that an event can become unsuscribed between the if
and the EventName(this,EventArgs.Empty)
- it's happened to me before.
(Hopefully these compile, I haven't tried)
public class Form1 : Form
{
int _count;
void ButtonClick(object sender, EventArgs e)
{
ThreadWorker worker = new ThreadWorker();
worker.ThreadDone += HandleThreadDone;
Thread thread1 = new Thread1(worker.Run);
thread1.Start();
_count = 1;
}
void HandleThreadDone(object sender, EventArgs e)
{
// You should get the idea this is just an example
if (_count == 1)
{
ThreadWorker worker = new ThreadWorker();
worker.ThreadDone += HandleThreadDone;
Thread thread2 = new Thread1(worker.Run);
thread2.Start();
_count++;
}
}
class ThreadWorker
{
public event EventHandler ThreadDone;
public void Run()
{
// Do a task
if (ThreadDone != null)
ThreadDone(this, EventArgs.Empty);
}
}
}
4. Use a delegate
public class Form1 : Form
{
int _count;
void ButtonClick(object sender, EventArgs e)
{
ThreadWorker worker = new ThreadWorker(HandleThreadDone);
Thread thread1 = new Thread1(worker.Run);
thread1.Start();
_count = 1;
}
void HandleThreadDone()
{
// As before - just a simple example
if (_count == 1)
{
ThreadWorker worker = new ThreadWorker();
Thread thread2 = new Thread1(worker.Run);
thread2.Start(HandleThreadDone);
_count++;
}
}
class ThreadWorker
{
// Switch to your favourite Action<T> or Func<T>
public void Run(object state)
{
// Do a task
Action completeAction = (Action)state;
completeAction.Invoke();
}
}
}
If you do use the _count method, it might be an idea (to be safe) to increment it using
Interlocked.Increment(ref _count)
I'd be interested to know the difference between using delegates and events for thread notification, the only difference I know are events are called synchronously.
5. Do it asynchronously instead
The answer to this question has a very clear description of your options with this method.
Delegate/Events on the wrong thread
The event/delegate way of doing things will mean your event handler method is on Thread1/Thread2 not the main UI thread, so you will need to switch back right at the top of the HandleThreadDone methods:
// Delegate example
if (InvokeRequired)
{
Invoke(new Action(HandleThreadDone));
return;
}