简体   繁体   English

如何避免在不阻塞的情况下并发调用方法?

[英]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.

相关问题 Unity中的C#:在不阻塞主线程的情况下调用Promise Style Async方法 - C# in Unity: Calling Promise Style Async method without Blocking the Main Thread Parallel.ForEach 阻塞调用方法 - Parallel.ForEach blocking calling method 有办法避免方法调用重复吗? - Is there a way to avoid method calling repetition? 理解等待或超时:如何同时发送多封邮件而不阻塞程序的rest - Understanding the await or timeout: How to send multiple emails concurrently without blocking the rest of the program 我可以同时从内存映射文件中读取(多个线程/进程)而不会阻塞/锁定吗? - Can I concurrently read (multiple threads/processes) from a memory mapped file without blocking/locking? 等待方法完成AutoResetEvent而不会阻塞UI - Wait for method to finish an AutoResetEvent without blocking UI ShowDialog方法而不会阻止WPF中的其他窗口 - ShowDialog method without blocking other windows in WPF 等待异步方法而不阻塞线程 - Wait for async method without blocking the thread 在同时调用方法时是否需要同步访问方法参数和本地? - Do I need to synchronize access the method arguments and locals when calling a method concurrently? 如何在不阻塞的情况下等待一个任务完成然后再调用另一个任务? - How to wait for one task to finish before calling another without blocking?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM