I’ve noticed a common pattern in some code I’m writing so I decided to extract it into a class. However, since starting to use this class I’ve been having a problem where every once in a while the program will hang indefinitely, and, from what I can tell from debugging, this class seems to be the cause. Could sometime tell me what I’m doing wrong? Thank you for your time.
Updated code:
class ParallelTaskWaiter
{
int numTasksRunning;
private readonly object completeLock = new object();
public void WaitFor(ThreadStart action)
{
Interlocked.Increment(ref numTasksRunning);
ThreadPool.QueueUserWorkItem(delegate
{
try { action(); }
finally
{
if (Interlocked.Decrement(ref numTasksRunning) == 0)
{
lock (completeLock)
{
Monitor.PulseAll(completeLock);
}
}
}
});
}
public void Wait()
{
lock (completeLock)
{
if (Interlocked.CompareExchange(ref numTasksRunning, 0, 0) == 0) return;
Thread.SpinWait(1);
Monitor.Wait(completeLock, Timeout.Infinite);
}
}
}
WAG here… Change
to
Its the safer bet, no matter what.
In addition, while you are interlocking the increment, you are still incrementing THEN queueing the work item. Incrementing and queueing should be atomic. I’d also use a
lockinstead of an interlocked increment.