c# lock and listen to CancellationToken

后端 未结 2 1055
粉色の甜心
粉色の甜心 2021-02-20 02:51

I want to use lock or a similar synchronization to protect a critical section. At the same time I want to listen to a CancellationToken.

Right now I\'m using a mutex lik

相关标签:
2条回答
  • 2021-02-20 03:29

    Take a look at the new .NET 4.0 Framework feature SemaphoreSlim Class. It provides SemaphoreSlim.Wait(CancellationToken) method.

    Blocks the current thread until it can enter the SemaphoreSlim, while observing a CancellationToken

    From some point of view using Semaphore in such simple case could be an overhead because initially it was designed to provide an access for multiple threads, but perhaps you might find it useful.

    EDIT: The code snippet

    CancellationToken token = new CancellationToken();            
    SemaphoreSlim semaphore = new SemaphoreSlim(1,1);
    bool tokenCanceled = false;
    
    try {
       try {
          // block section entrance for other threads
          semaphore.Wait(token);
       }
       catch (OperationCanceledException) {
          // The token was canceled and the semaphore was NOT entered...
          tokenCanceled = true;
       }
       // critical section code
       // ...
       if (token.IsCancellationRequested)
       {
           // ...
       }
    }
    finally { 
       if (!tokenCanceled)
          semaphore.Release();
    }
    
    0 讨论(0)
  • 2021-02-20 03:38
    private object _lockObject = new object();
    
    lock (_lockObject)
    {  
       // critical section  
       using (token.Register(() => token.ThrowIfCancellationRequested())
       {
           // Do something that might need cancelling. 
       }
    }
    

    Calling Cancel() on a token will result in the ThrowIfCancellationRequested() being invoked as that was what is hooked up to the Register callback. You can put whatever cancellation logic you want in here. This approach is great because you can cancel blocking calls by forcing the conditions that will cause the call to complete.

    ThrowIfCancellationRequested throws a OperationCanceledException. You need to handle this on the calling thread or your whole process could be brought down. A simple way of doing this is by starting your task using the Task class which will aggregate all the exceptions up for you to handle on the calling thread.

    try
    {
       var t = new Task(() => LongRunningMethod());
       t.Start();
       t.Wait();
    }
    catch (AggregateException ex)
    {
       ex.Handle(x => true); // this effectively swallows any exceptions
    }
    

    Some good stuff here covering co-operative cancellation

    0 讨论(0)
提交回复
热议问题