views:

292

answers:

1

I have a manager class that produces tasks for a threadpool, and each thread is supposed to do a call back once they are finished.

I use locks to handle variables and fields, and signals to handle interthread communications. What I'm looking for is a way of exiting the current lock() and wait for a signal atomically, something like SignalAndWait, but for locks().

The code looks something like this:

// ... part of the scheduler
foreach(WorkTask task in worktasks)
{
   lock(_syncObj)
   {
      new Job(task, myCallback); // creates a thread
      instanceCount++;
      while(instanceCount > _maxConcurrentTasks)
          _resetEvent.WaitOne(Timeout.Infinite);
   }
}

// .. the callback

void myCallback()
{
    lock(_syncObj)
    {
        instanceCount--;
        _resetEvent.Set();
    }
}

The problem here is that .WaitOne() doesn't exit the lock(), so any thread doing a callback will dead-lock.

I had high hopes for WaitOne(Int32, bool exitContext), but that context seems to be about remoting and stuff rather than synchronisations.

+2  A: 

Is there any reason for using the event primitives rather than Monitor.Wait/Pulse/PulseAll? Monitor.Wait atomically releases the lock and waits, reacquiring the lock before it returns. See my threading article for more details.

Jon Skeet
No reason besides not knowing about Pulse/PulseAll. Thanks!
Mats Fredriksson