5

I am using multiple threads in my application using while(true) loop and now i want to exit from loop when all the active threads complete their work.

rerun
  • 25,014
  • 6
  • 48
  • 78
Muhammad Waqas
  • 105
  • 1
  • 1
  • 6
  • Not entirely dissimilar from this question & answer: http://stackoverflow.com/questions/435668/code-for-a-simple-thread-pool-in-c – xcud Mar 08 '10 at 06:26
  • whats your loop like? Are you using it to create threads? Or are you using it to wait on threads to complete there tasks? – ata Mar 08 '10 at 06:27

6 Answers6

5

Assuming that you have a list of the threads themselves, here are two approaches.

Solution the first:

Use Thread.Join() with a timespan parameter to synch up with each thread in turn. The return value tells you whether the thread has finished or not.

Solution the second:

Check Thread.IsAlive() to see if the thread is still running.

In either situation, make sure that your main thread yields processor time to the running threads, else your wait loop will consume most/all the CPU and starve your worker threads.

zero323
  • 322,348
  • 103
  • 959
  • 935
Bevan
  • 43,618
  • 10
  • 81
  • 133
  • In case of Join, the thread calling the Join method will wait for it to return. In case of Thread.IsAlive, you will have to poll some specified number of time (like 1 second). It would be the same as calling Join method, the calling thread will have to wait until all threads terminate. So better use Thread.Join() – ata Mar 08 '10 at 09:48
  • The key difference is that polling IsAlive() allows your main thread to continue doing other work, if there is any. Good points though - if there's no work to be done, Join() is the more efficient choice. – Bevan Mar 09 '10 at 07:19
2

You can use Process.GetCurrentProcess().Threads.Count.

Anonymous
  • 9,366
  • 22
  • 83
  • 133
  • The solution Process.GetCurrentProcess().Threads.Count doesn't work. It returns all the processes running but i need the count of threads running that i have creating in my application. – Muhammad Waqas Mar 08 '10 at 06:12
  • Process.GetCurrentProcess().Threads.Count indeed return number of thread for current process, if you need to count all thread of all processes you need to loop thought processes in your application – Anonymous Mar 08 '10 at 06:39
  • That will also involve thread pool threads. Though you can get the count before creating thread, but it still won't guarantee that its your custom threads who are terminated when the count decreases. – ata Mar 08 '10 at 09:45
1

There are various approaches here, but utlimately most of them come down to your changing the executed threads to do something whenever they leave (success or via exception, which you don't want to do anyway). A simple approach might be to use Interlock.Decrement to reduce a counter - and if it is zero (or -ve, which probably means an error) release a ManualResetEvent or Monitor.Pulse an object; in either case, the original thread would be waiting on that object. A number of such approaches are discussed here.

Of course, it might be easier to look at the TPL bits in 4.0, which provide a lot of new options here (not least things like Parallel.For in PLINQ).

If you are using a synchronized work queue, it might also be possible to set that queue to close (drain) itself, and simply wait for the queue to be empty? The assumption here being that your worker threads are doing something like:

T workItem;
while(queue.TryDequeue(out workItem)) { // this may block until either something
   ProcessWorkItem(workItem);           // todo, or the queue is terminated
}
// queue has closed - exit the thread

in which case, once the queue is empty all your worker threads should already be in the process of suicide.

Community
  • 1
  • 1
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
0

I find that using the Join() method is the cleanest way. I use multiple threads frequently, and each thread is typically loading data from different data sources (Informix, Oracle and SQL at the same time.) A simple loop, as mentioned above, calling Join() on each thread object (which I store in a simple List object) works!!!

Carlos Merighe.

0

You can use Thread.Join(). The Join method will block the calling thread until the thread (the one on which the Join method is called) terminates.

So if you have a list of thread, then you can loop through and call Join on each thread. You loop will only exit when all the threads are dead. Something like this:

for(int i = 0 ;i < childThreadList.Count; i++)
{
    childThreadList[i].Join();
}
///...The following code will execute when all threads in the list have been terminated...///
ata
  • 8,853
  • 8
  • 42
  • 68
0

I prefer using a HashSet of Threads:

// create a HashSet of heavy tasks (threads) to run
HashSet<Thread> Threadlist = new HashSet<Thread>();
Threadlist.Add(new Thread(() => SomeHeavyTask1()));
Threadlist.Add(new Thread(() => SomeHeavyTask2()));
Threadlist.Add(new Thread(() => SomeHeavyTask3()));

// start the threads
foreach (Thread T in Threadlist)
  T.Start();

// these will execute sequential
NotSoHeavyTask1();
NotSoHeavyTask2();
NotSoHeavyTask3();

// loop through tasks to see if they are still active, and join them to main thread
foreach (Thread T in Threadlist)
  if (T.ThreadState == ThreadState.Running)
    T.Join();

// finally this code will execute
MoreTasksToDo();
RooiWillie
  • 2,198
  • 1
  • 30
  • 36