c# - How can I wait for a thread to finish with .NET?

ID : 20243

viewed : 9

Tags : c#multithreadingc#

Top 5 Answer for c# - How can I wait for a thread to finish with .NET?

vote vote

100

I can see five 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 unsubcribed 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 Thread(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 Thread(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();          Thread thread1 = new Thread(worker.Run);         thread1.Start(HandleThreadDone);          _count = 1;     }      void HandleThreadDone()     {         // As before - just a simple example         if (_count == 1)         {             ThreadWorker worker = new ThreadWorker();              Thread thread2 = new Thread(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; } 
vote vote

90

Add

t1.Join();    // Wait until thread t1 finishes 

after you start it, but that won't accomplish much as it's essentialy the same result as running on the main thread!

I can highly recommended reading Joe Albahari's Threading in C# free e-book, if you want to gain an understanding of threading in .NET.

vote vote

77

If using from .NET 4 this sample can help you:

class Program {     static void Main(string[] args)     {         Task task1 = Task.Factory.StartNew(() => doStuff());         Task task2 = Task.Factory.StartNew(() => doStuff());         Task task3 = Task.Factory.StartNew(() => doStuff());         Task.WaitAll(task1, task2, task3);         Console.WriteLine("All threads complete");     }      static void doStuff()     {         // Do stuff here     } } 

From: Create multiple threads and wait all of them to complete

vote vote

64

The previous two answers are great and will work for simple scenarios. There are other ways to synchronize threads, however. The following will also work:

public void StartTheActions() {     ManualResetEvent syncEvent = new ManualResetEvent(false);      Thread t1 = new Thread(         () =>         {             // Do some work...             syncEvent.Set();         }     );     t1.Start();      Thread t2 = new Thread(         () =>         {             syncEvent.WaitOne();              // Do some work...         }     );     t2.Start(); } 

ManualResetEvent is one of the various WaitHandle's that the .NET framework has to offer. They can provide much richer thread synchronization capabilities than the simple, but very common tools like lock()/Monitor, Thread.Join, etc.

They can also be used to synchronize more than two threads, allowing complex scenarios such as a 'master' thread that coordinates multiple 'child' threads, multiple concurrent processes that are dependent upon several stages of each other to be synchronized, etc.

vote vote

53

You want the Thread.Join() method, or one of its overloads.

Top 3 video Explaining c# - How can I wait for a thread to finish with .NET?

Related QUESTION?