How can I achieve a thread-safe cancellation of the previous task?

72 Views Asked by At

In the event handler for the "connect" event, I need to start a task that may take a long time to complete, and I need to wait for its result. While the task is running, the "connect" event may be raised again, which should interrupt the previous operation and start a new one.

The problem is that the "connect" event can be raised from different threads. So cancellation of the previous task should be thread safe. How can I achieve a thread-safe cancellation of the previous task?

I found these two answers but none of them contains a thread-safe solution:

I came up with a following solution (which is not thread-safe):

CancellationTokenSource cts;
        
async void OnConnected() 
{
    cts?.Cancel();
    var currentCts = cts = new CancellationTokenSource();   

    try
    {
        var result = await LongRunningTask(currentCts.Token);
        //Do something with result if LongRinningTask was not cancelled
    }
    finally
    {
        currentCts.Dispose();               
    }
}
    
await Task<bool> LongRunningTask(CancellationToken ct)
{
    try
    {
        await Task.Delay(TimeSpan.FromHours(1), ct);
        return true;
    }       
    catch(Exception)
    {
        return false;
    }
}

Is it sufficient to achieve thread-safety just wrap the work with CancellationTokonSource in the lock statement? Like that:

CancellationTokenSource cts;
readonly object ctsSync = new object();
        
async void OnConnected() 
{
    lock(ctsSync)
    {
        cts?.Cancel();
        var currentCts = cts = new CancellationTokenSource();   
    }

    try
    {
        var result = await LongRunningTask(currentCts.Token);
        //Do something with result if LongRinningTask was not cancelled
    }
    finally
    {
        currentCts.Dispose();               
    }
}
    

Is there better solution for these kind of problems?

0

There are 0 best solutions below