簡體   English   中英

如何避免在不阻塞的情況下並發調用方法?

[英]Howto avoid concurrently calling a method without blocking?

我想運行一個可能運行幾秒鍾的清理任務。 多個線程可以調用此任務,但我只想運行一次此任務。 所有其他發票都應該跳過。

以下是我當前的實現,但是我無法想象.net框架中沒有更好的解決方案,導致更少的代碼行。

    object taskLock;
    bool isRunning;

    void Task()
    {
        if (isRunning) return;

        try
        {
            lock (taskLock)
            {
                if (isRunning) return;
                isRunning = true;
            }
            // Perform the magic
        }
        finally
        {
            isRunning = false;
        }
    }

是的,有更好的解決方案。 您可以使用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
    }
}

在這種情況下, Interlocked.CompareExchange作為原子操作(偽代碼)執行以下操作:

wasRunning = isRunning;
if isRunning = 0 then 
     isRunning = 1
end if
return wasRunning

從MSDN文檔中:

public static int CompareExchange(
    ref int location1,
    int value,
    int comparand
)

如果比較數與location1中的值相等,則將值存儲在location1中。 否則,將不執行任何操作。 比較和交換操作作為原子操作執行。 無論交換是否發生,CompareExchange的返回值都是location1中的原始值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM