How to block part of a method from other threads?
an effective way is mutual exchange; by setting some token field to a value other than the default at runtime, other threads can check this and exit. For example:
private int hazWorker; // = 0 - put this at the scope you want to protect
then
// means: atomically set hazWorker to 1, but only if the old value was 0, and
// tell me what the old value was (and compare that result to 0)
if(Interlocked.CompareExchange(ref hazWorker, 1, 0) != 0) {
return; // someone else has the conch
}
try {
// your work here
} finally {
Interlocked.Exchange(ref hazWorker, 0); // set it back to default
}
source to share
You can use Monitor.TryEnter for this purpose.
if(!Monitor.TryEnter(someLock))
{
return;
}
try
{
//Critical region
}
finally
{
Monitor.Exit(someLock);
}
Or a more reliable way to deal with Rude Thread aborts (suggested by marc in the comments)
bool lockTaken = false;
try
{
Monitor.TryEnter(someLock, ref lockTaken);
if (lockTaken)
{
//Critical region
}
}
finally
{
if(lockTaken) Monitor.Exit(someLock);
}
Note that this does not check if it is working threads[0]
, but it does check if any other thread is in the critical region. If so, it exits the method.
source to share
You can use bool to set it to "false" by default, and then the first stream sets it to "true". And then a piece of code might look like this:
if (!alreadyExecuted)
{
// ...
alreadyExecuted = true;
}
I would also put the code in a lock to make sure only one thread is executing it at a time (to resolve any possible race conditions) as shown below.
lockVariable is a lock variable and can be of any reference type, for example. object lockVariable = new object ();
lock (lockVariable)
{
if (!alreadyExecuted)
{
// ...
alreadyExecuted = true;
}
}
source to share