views:

140

answers:

4

Greetings

I have a program that creates multiples instances of a class, runs the same long-running Update method on all instances and waits for completion. I'm following Kev's approach from this question of adding the Update to ThreadPool.QueueUserWorkItem.

In the main prog., I'm sleeping for a few minutes and checking a Boolean in the last child to see if done

while(!child[child.Length-1].isFinished) {
    Thread.Sleep(...);
}

This solution is working the way I want, but is there a better way to do this? Both for the independent instances and checking if all work is done.

Thanks

UPDATE: There doesn't need to be locking. The different instances each have a different web service url they request from, and do similar work on the response. They're all doing their own thing.

+1  A: 

You can try Semaphore.

Anton Gogolev
Wrong way around, you'd need a reverse semaphore (aka CountdownLatch).
Hans Passant
+1  A: 

A blocking way of waiting is a bit more elegant than polling. See the Monitor.Wait/Monitor.Pulse (Semaphore works ok too) for a simple way to block and signal. C# has some syntactic sugar around the Monitor class in the form of the lock keyword.

Wout
+1  A: 

If you know the number of operations that will be performed, use a countdown and an event:

Activity[] activities = GetActivities();
int remaining = activities.Length;
using (ManualResetEvent finishedEvent = new ManualResetEvent(false))
{
    foreach (Activity activity in activities)
    {
        ThreadPool.QueueUserWorkItem(s =>
        {
            activity.Run();
            if (Interlocked.Decrement(ref remaining) == 0)
                finishedEvent.Set();
        });
    }
    finishedEvent.WaitOne();
}

Don't poll for completion. The .NET Framework (and the Windows OS in general) has a number of threading primitives specifically designed to prevent the need for spinlocks, and a polling loop with Sleep is really just a slow spinlock.

Aaronaught
Awesome. Incorporated into mine and works great. Thanks!
adamcodes
+1  A: 

This doesn't look good. There is almost never a valid reason to assume that when the last thread is completed that the other ones are done as well. Unless you somehow interlock the worker threads, which you should never do. It also makes little sense to Sleep(), waiting for a thread to complete. You might as well do the work that thread is doing.

If you've got multiple threads going, give them each a ManualResetEvent. You can wait on completion with WaitHandle.WaitAll(). Counting down a thread counter with the Interlocked class can work too. Or use a CountdownLatch.

Hans Passant