[英]Howto avoid concurrently calling a method without blocking?
I want to run a cleanup task that might run for several seconds. 我想运行一个可能运行几秒钟的清理任务。 Multiple threads could call this task but I want to run this task only once. 多个线程可以调用此任务,但我只想运行一次此任务。 All other invokations should just skip. 所有其他发票都应该跳过。
The following is my current implementation but I cannot imagine there is not a better solution in the .net framework resulting in less lines of code. 以下是我当前的实现,但是我无法想象.net框架中没有更好的解决方案,导致更少的代码行。
object taskLock;
bool isRunning;
void Task()
{
if (isRunning) return;
try
{
lock (taskLock)
{
if (isRunning) return;
isRunning = true;
}
// Perform the magic
}
finally
{
isRunning = false;
}
}
Yes, there is a better solution. 是的,有更好的解决方案。 You can use Interlocked.CompareExchange , the code becomes simpler and lock-free: 您可以使用Interlocked.CompareExchange ,代码变得更加简单和无锁:
class Worker
{
private volatile int isRunning = 0;
public void DoWork()
{
if (isRunning == 0 && Interlocked.CompareExchange(ref isRunning, 1, 0) == 0)
{
try
{
DoTheMagic();
}
finally
{
isRunning = 0;
}
}
}
private void DoTheMagic()
{
// do something interesting
}
}
In this case Interlocked.CompareExchange
does the following as an atomic operation (pseudo-code): 在这种情况下, Interlocked.CompareExchange
作为原子操作(伪代码)执行以下操作:
wasRunning = isRunning;
if isRunning = 0 then
isRunning = 1
end if
return wasRunning
From the MSDN documentation: 从MSDN文档中:
public static int CompareExchange(
ref int location1,
int value,
int comparand
)
If comparand and the value in location1 are equal, then value is stored in location1. 如果比较数与location1中的值相等,则将值存储在location1中。 Otherwise, no operation is performed. 否则,将不执行任何操作。 The compare and exchange operations are performed as an atomic operation. 比较和交换操作作为原子操作执行。 The return value of CompareExchange is the original value in location1, whether or not the exchange takes place 无论交换是否发生,CompareExchange的返回值都是location1中的原始值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.