views:

473

answers:

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.

A: 

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

In The Pink
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
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
In The Pink
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.
cornerback84
Thank you @cornerback84, I will try to study this more.
In The Pink
you'r welcome..
cornerback84
+1  A: 

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.

Marc Gravell
+2  A: 

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 yeilds processor time to the running threads, else your wait loop will consume most/all the CPU and starve your worker threads.

Bevan
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()
cornerback84
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
A: 

I liked the Interlocked.Decrement suggestion. I didn't find a sample handy on the link. Is this what you have mind Marc?

int threadCount = 10;

long locks = threadCount;
ManualResetEvent poolComplete = new ManualResetEvent(false);
for (int i = 0; i < threadCount; i++)
{
    ThreadPool.QueueUserWorkItem(delegate(Object threadContext)
    {
        // do something other than wait 1-10 seconds
        Thread.Sleep(new TimeSpan(0, 0, (new Random()).Next(1, 10)));

        Console.WriteLine("Thread {0} done.",
            Thread.CurrentThread.ManagedThreadId);
        if (Interlocked.Decrement(ref locks) == 0)
            poolComplete.Set();
    });
}
poolComplete.WaitOne();
Console.WriteLine("All Done");
xcud
A: 

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...///
cornerback84