【问题标题】:c# lock and listen to CancellationToken时间:2019-05-10 标签:c#lock and listen to CancellationToken
【发布时间】:2011-09-14 13:05:32
【问题描述】:

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

现在我正在使用这样的互斥锁,但互斥锁没有那么好的性能。我可以使用任何其他同步类(包括新的 .Net 4.0)来代替互斥锁吗?

WaitHandle.WaitAny(new[] { CancelToken.WaitHandle, _mutex});
CancelToken.ThrowIfCancellationRequested();

【问题讨论】:

  • 您能否发布一些代码来显示关键部分以及您当前如何释放互斥锁?

标签: c# multithreading .net-4.0 task-parallel-library cancellation-token


【解决方案1】:

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

阻塞当前线程,直到它可以进入 SemaphoreSlim,而 观察 CancellationToken

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

编辑:代码 sn-p

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

【讨论】:

  • 拜托,最后试一下:-)
  • @xanatos :你的意思是有什么例外?这是演示 SemaphoreSlim 如何与 CancellationToken 绑定的伪代码,仅此而已:)
  • @xanatos ...为什么不自己做呢?
  • @sll ...不,您应该这样做以确保无论如何释放信号量
  • @Carsten König:感谢增强 sn-p!
【解决方案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 涵盖合作取消

【讨论】:

  • 如果您的意思是 OperationCanceledException,那么这是设计使然 - 这就是 ThrowIfCancellationRequested 方法抛出的内容。您应该使用推荐的模式(更新的答案)在调用者上处理它。
  • “调用Cancel()上的t̶̶k̶e̶n̶unclationtokensource将导致ThrowIfCancellationRequested()被调用”...可以使用Cancel(bool)超载来控制此行为。 span>
  • ThrowIfCancellationRequested注册为取消操作根本没有任何意义。这只是意味着任何调用CancellationTokenSource.Cancel 的人都会得到一个异常,它甚至对令牌的接收者根本没有做任何事情。
猜你喜欢
  • 2011-11-01
  • 2011-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-18
  • 2020-06-15
  • 2020-10-01
  • 2015-06-14
相关资源
最近更新 更多