views:

359

answers:

3

I have a parent thread (non-UI) which creates some child threads to do some jobs - at some point the parent must wait for certain tasks to be completed by the child thread - this does not mean the child is finished but only that it has reached a certain point and the parent can now continue processing ...

To illustrate please refer to the code below, obviously this isn't what my children do but it shows what I am trying to accomplish. Recall that none of these are UI threads...

// Parent Thread
Thread childThread = new Thread(new ThreadStart(Manage));
childThread.IsBackground = true;
childThread.Name = "NamedPipe Manager";
childThread.Start();

while (true)
{
... do some work ...

// wait for signal from MainThread to proceed //

... do more work
}


// Child Thread
private void Manage()
{
... do some work ...
... call some functions ...

// SIGNAL TO PARENT THAT IT CAN CONTINUE //

... do more work ...
... call more functions ...
}

Any one have any suggestions on how I can accomplish this task in a thread-safe manner? Any help would be much appreciated. Thanks,

+1  A: 

You can do this using a WaitHandle (I would add the usual code sample, but the example given in MSDN is almost exactly what you want)

Martin Harris
Seriously? you can just make the autoevent static? I thought I would need to create the AutoEvent and somehow pass it to the children thread ... but this is a lot easier then I thought ...And it is thread safe? Even if I have multiple children? (only need a single signal)
Shaitan00
Yes seriously, yes it can be static, yes it is thread safe and yes the parent thread will move past the WaitOne() call until *any* other thread sets the WaitHandle. You can use multiple WaitHandles and the WaitAll call to wait for *all* the child threads to call Set()
Martin Harris
A: 

If there's a single child thread you can use a ManualResetEvent:

var signal = new ManualResetEvent(false);

// child thread: signal to parent that it can continue
signal.Set();

// parent thread: wait for signal from child thread to proceed
signal.WaitOne();

If there's more than one child thread you can use a Semaphore:

var semaphore = new Semaphore(0, numberOfChildThreads);

// child thread: signal to parent that it can continue
semaphore.Release();

// parent thread: wait for signal from each child thread to proceed
for (int i = 0; i < numberOfChildThreads; i++)
{
    semaphore.WaitOne();
}
dtb
What happens if they are in another class? For example Pareant creates A = new A(); and inside A we launch a thread that needs to .Set() the ManualResetEvent() in the parent?
Shaitan00
Pass the signal reference along as a parameter to the A constructor
dtb
A: 

Is there a reason you're using explicit threads instead of BackgroundWorker? BackgroundWorker has built-in facilities for communicating progress back to the UI thread.

Joe White
There is no UI thread ... this is actually a Service.Do you still recommend using BackgroundWorkers?
Shaitan00
Hmm. No idea; I've never tried it, and I don't know much about its implementation, so I couldn't say. So one of the other answers may be a better bet.
Joe White