简体   繁体   中英

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.

    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:

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):

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

From the MSDN documentation:

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. 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM