Suppose I am processing a large amount of incoming data from multiple threads. I may want for this data to act as a trigger for a specific action when certain criteria are met. However, the action is not reentrant; so the same trigger being fired twice in rapid succession should only cause the action to run once.
Using a simple bool
flag to indicate whether the action is currently running is not a robust solution, as a race condition could occur and two (or more) threads could still end up running the same action concurrently after all. A bool
within a lock
statement on a synchronization object would work, of course; but I generally prefer to avoid locking whenever possible*.
Currently what I do in these cases is use an AutoResetEvent
as essentially a form of atomic switch. The code typically looks something like this:
if (conditionMet && readyForAction.WaitOne(0))
{
try
{
doAction();
}
finally
{
readyForAction.Set();
}
}
This works, but it strikes me that this may be a less-than-ideal use case for the AutoResetEvent
class. Would you say this is an appropriate solution to this problem, or would it make more sense to use some other mechanism?
Update: As Jon pointed out, using Monitor.TryEnter
as the locking strategy (instead of the simple lock
, which I believe is roughly equivalent to Monitor.Enter
), is really quite straightforward:
if (conditionMet && Monitor.TryEnter(lockObject))
{
try
{
doAction();
}
finally
{
Monitor.Exit(lockObject);
}
}
That said, I'm strongly inclined to go with Henk's idea of using Interlocked
. That seems about as simple as it gets.