views:

123

answers:

6

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?

+3  A: 

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.

SimpleCoder
+1  A: 

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: http://stackoverflow.com/questions/263116/c-waiting-for-all-threads-to-complete

Steve Townsend
+5  A: 

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)

lasseespeholt
thank you, this is exactly what I was looking for. Do you know any tutorials for the Library?
AKRamkumar
This website; http://www.albahari.com/threading/part4.aspx has information on C# 4.0's latest threading features
SimpleCoder
@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
lasseespeholt
SimpleCoder
+2  A: 

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
A: 

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
A: 

My thought on the problem

You can use ManualResetEvent.

My thought on the problem

Use ManualResetEvents

Class ThreadSample

{

ManualResetEvent mReset = new ManualResetEvent(false);

public void SpawnThreads()

  {
for(int i =0;i<=20;i++)
    {
        Thread t = new Thread(new ThreadStartDelegate(Dowork));
            t.start();
    }

mReset.WaitOne();
   }

public void DoWork()

{ // set manually reset event.After your processing is finsihed

mReset.set();

}

}

saurabh
This does not look correct as it stands. WaitOne() will return as soon as the first thread signals the event via Set(). You don't want WaitOne() inside the loop as this serializes the 20 threads behind each other.
Steve Townsend
nope , i have initilized ManualResetEvent with false state so when you call WaitOne after for loop current thread will be the main thread and it will stop from processing when you call set from DoWork , it will release the main thread.
saurabh