问题
I have a method in a multi-threaded application and I'd like the following behavior when this method is invoked:
- If no other threads are currently executing the method, execute it.
- If another thread is currently executing the method then exit the method without executing it.
The lock
statement in C# is useful for waiting until a thread has completed execution, but I don't want to serialize access to this method but rather bypass executing said method if it is being executed by another thread.
回答1:
I suppose I don't understand... if it should only be called by one thread at a time, why are multiple threads calling it to begin with?
Anyway, you can use Monitor.TryEnter(). It doesn't block and returns false
if it fails to acquire a lock. In that case you can just return from the function.
回答2:
You can do this using Monitor.TryEnter, but perhaps more simply: Interlocked:
int executing; // make this static if you want this one-caller-only to
// all objects instead of a single object
void Foo() {
bool won = false;
try {
won = Interlocked.CompareExchange(ref executing, 1, 0) == 0;
if(won) {
// your code here
}
} finally {
if(won) Interlocked.Exchange(ref executing, 0);
}
}
回答3:
create bool variable somewhere else, set on true when start method and to false on exit from method, before run method check if variable is false then run else exit from method
回答4:
Here's a helper method for this purpose:
static class Throttle
{
public static void RunExclusive(ref int isRunning, Action action)
{
if (isRunning > 0) return;
bool locked = false;
try
{
try { }
finally
{
locked = Interlocked.CompareExchange(ref isRunning, 1, 0) == 0;
}
if (locked) action();
}
finally
{
if (locked)
Interlocked.Exchange(ref isRunning, 0);
}
}
}
and use it like:
private int _isTuning = 0;
private void Tune() { ... }
...
Throttle.RunExclusive(ref _isTuning, Tune);
来源:https://stackoverflow.com/questions/12412204/exit-a-method-if-another-thread-is-executing-it