c#锁定并收听CancellationToken

问题描述 投票:8回答:2

我想使用锁定或类似的同步来保护关键部分。同时,我想听一个CancellationToken。

目前,我正在使用这样的互斥锁,但是互斥锁的性能不佳。我可以使用任何其他同步类(包括新的.Net 4.0)代替互斥体吗?

WaitHandle.WaitAny(new[] { CancelToken.WaitHandle, _mutex});
CancelToken.ThrowIfCancellationRequested();
c# multithreading .net-4.0 task-parallel-library cancellation-token
2个回答
12
投票

查看新的.NET 4.0 Framework功能SemaphoreSlim Class。它提供SemaphoreSlim.Wait(CancellationToken)方法。

阻止当前线程,直到它可以进入SemaphoreSlim,同时观察CancellationToken

从某种角度来看,在这种简单情况下使用Semaphore可能会产生开销,因为最初它是为提供对多个线程的访问而设计的,但也许您会发现它很有用。

编辑:代码段

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();
}

2
投票
private object _lockObject = new object();

lock (_lockObject)
{  
   // critical section  
   using (token.Register(() => token.ThrowIfCancellationRequested())
   {
       // Do something that might need cancelling. 
   }
}

在令牌上调用Cancel()将导致调用ThrowIfCancellationRequested(),因为这是连接到Register回调的内容。您可以在此处输入任何取消逻辑。这种方法非常有用,因为您可以通过强制执行将导致呼叫完成的条件来取消阻止呼叫。

ThrowIfCancellationRequested引发OperationCanceledException。您需要在调用线程上处理此问题,否则整个过程可能会崩溃。一种简单的方法是使用Task类启动任务,该类将汇总所有异常供您在调用线程上处理。

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

涉及合作取消的一些好东西here

© www.soinside.com 2019 - 2024. All rights reserved.