I have multiple threads that share use of a semaphore. Thread A holds the semaphore (using lock) and threads B and C are waiting on that same semaphore (also using lock). The threads share global variables, etc.
Is there a technique in C# that I can use to shut down thread B? I can set a flag in A and have thread B check that flag and exit as soon as it gets control of the semaphore, but I don't know of any technique to allow thread A to yield the semaphore to thread B (and get it back when thread B exits) without the risk of thread C seizing control.
Anyone have any suggestions how to address this design problem? I can rewrite the program as necessary if I am approaching this incorrectly.
[Edit] A commenter has pointed out that I am using the wrong terminology. The commenter is correct - I am using a critical section, but given that everything is running in a single process, in this example critical sections are functionally equivalent to the more general term 'semaphore'.
[Edit] Someone asked for more details, so here it is.
There can be multiple threads executing Code A. There's only ever one thread executing Code B.
Code A:
private static Thread workerThread = null;
lock (lockObject)
{
... do some work ...
if (...condition...)
{
if (workerThread != null)
{
// Kill the worker thread and continue only after it is dead.
quitWorkerThread = true;
// Wait for the thread to die.
while (workerThread.IsAlive)
{
Thread.Sleep(50);
}
workerThread = null;
quitWorkerThread = false;
} // if (workerThread != null)
} // if (...condition...)
... do some more work ...
if (...condition...)
{
if (workerThread == null)
{
// Start the worker thread.
workerThread = new Thread(WorkerThread);
workerThread.Start();
} // if (workerThread == null)
} // if (...condition...)
... do even more work ...
} // lock (lockObject)
Code B:
private void WorkerThread()
{
while (true)
{
if (quitWorkerThread)
{
return;
}
Thread.Sleep (2000);
if (quitWorkerThread)
{
return;
}
lock(lockObject)
{
if (quitWorkerThread)
{
return;
}
... do some work ...
} // lock(lockObject)
} // while (true)
} // WorkerThread
I suspect that a variant of Aaron's solution will be what I use. I was mostly hoping there was somewhat more elegant solution was available, but I suspect that like everything else about this project, it's all brute force and corner cases :-(.