8

I have a Main thread that spawns around 20 worker threads.
I need to stop the Main thread until all the other threads are finished.
I know about (thread).Join. But that only works for one thread.

and multiple Joins hurt performance like this.

t1.Join()
t2.Join()
...
t20.Join()

as the program waits one by one for each to stop.

How would I make it such that the main thread waits for all of a set of threads to end?

akshaykarthik
  • 1,055
  • 2
  • 13
  • 30
  • 5
    This is desired behaviour, right? It doesn't really matter that it waits for t1 first (while t3 is possible done allready), in the end, when the callstackpointer crosses past `t20.Join;` you know that all threads are stopped. – astellin Sep 05 '10 at 14:37
  • See also http://stackoverflow.com/questions/263116/c-waiting-for-all-threads-to-complete – JSBձոգչ Sep 05 '10 at 14:41
  • Treating threads like candy is a common mistake. Only start 20 threads when you have a machine with at least 20 CPU cores. Starting more actually slows down your program. Getting the locking right for so many threads is also *very* difficult, you typically just get threads waiting for each other. – Hans Passant Sep 05 '10 at 14:57
  • Essentially, I have to load 20 different files into my program. the threads don't have to interact. And I wanted it to work regardless of how many cores the computer had. Also, I needed the main program to wait until all 20 files are opened. – akshaykarthik Sep 05 '10 at 15:01
  • 3
    Actually, starting 20 threads wouldn't necessarily be out of line, if they were all IO-bound. – Joe White Sep 05 '10 at 15:01
  • any final solution with full source code working ? maybe more complex sample for notify errors in each thread and after WaitAll shows a summary ? – Kiquenet Jan 01 '14 at 10:52

5 Answers5

11

You should really look into Task Parallelism (Task Parallel Library). It uses a thread-pool, but also manage task-stealing etc.

Quote: "The TPL scales the degree of concurrency dynamically to most efficiently use all the processors that are available. In addition, the TPL handles the partitioning of the work, the scheduling of threads on the ThreadPool, cancellation support, state management, and other low-level details." on Task Parallel Library

You can use it like this:

Task[] tasks = new Task[3]
{
    Task.Factory.StartNew(() => MethodA()),
    Task.Factory.StartNew(() => MethodB()),
    Task.Factory.StartNew(() => MethodC())
};

//Block until all tasks complete.
Task.WaitAll(tasks);

Or if you use some kind of a loop to spawn your threads:

Data Parallelism (Task Parallel Library)

Lasse Espeholt
  • 17,622
  • 5
  • 63
  • 99
  • thank you, this is exactly what I was looking for. Do you know any tutorials for the Library? – akshaykarthik Sep 05 '10 at 14:55
  • This website; http://www.albahari.com/threading/part4.aspx has information on C# 4.0's latest threading features – Chris Laplante Sep 05 '10 at 15:00
  • @AKRamkumar Cool :) Hhm, not something in particular :/ a guess google can come up with something decent or otherwise look for a good .Net Framework 4.0 or C# 4.0 book. Maybe this article: http://msdn.microsoft.com/en-us/magazine/cc163340.aspx – Lasse Espeholt Sep 05 '10 at 15:01
  • A good C# book is http://www.amazon.com/Professional-4-0-NET-Wrox-Programmer/dp/0470502258/ref=sr_1_10?ie=UTF8&s=books&qid=1283699787&sr=8-10 – Chris Laplante Sep 05 '10 at 15:16
  • any final solution with full source code working ? maybe more complex sample for notify errors in each thread and after WaitAll shows a summary ? – Kiquenet Jan 01 '14 at 10:50
4

The joins are fine if that's what you want it to do. The main thread still has to wait for all the worker threads to terminate. Check out this website which is a sample chapter from C# in a Nutshell. It just so happens to be the threading chapter: http://www.albahari.com/threading/part4.aspx.

Chris Laplante
  • 29,338
  • 17
  • 103
  • 134
2

I can't see an obvious performance penalty for waiting for the threads to finish one-by-one. So, a simple foreach does what you want without any unnecerrasy bells and whistles:

foreach (Thread t in threads) t.Join();

Note: Of course, there's a Win32 API function that allows waiting for several objects (threads, in this case) at once — WaitForMultipleObjectsEx. There are many helper classes or threading frameworks out there on the Internet that utilize it for what you want. But do you really need them for a simple case?

Ondrej Tucny
  • 27,626
  • 6
  • 70
  • 90
2

and multiple Joins hurt performance like this.

There's no "performance hurting", if you want to wait for all of your threads to exit, you call .join() on the threads.

Stuff your threads in a list and do

foreach(var t in myThread)
     t.join();
nos
  • 223,662
  • 58
  • 417
  • 506
1

If you are sure you will always have < 64 threads then you could have each new thread reliably set an Event before it exits, and WaitAll on the events in your main thread, once all threads are started up. The Event object would be created in the main thread and passed to the relevant child thread in a thread-safe way at thread creation time.

In native code you could do the same thing on the thread handles themselves, but not sure how to do this in .Net.

See also this prior question: C#: Waiting for all threads to complete

Community
  • 1
  • 1
Steve Townsend
  • 53,498
  • 9
  • 91
  • 140