SemaphoreSlim.Wait(CancellationToken)正确尝试/最终为OperationCancelledException?

时间:2011-06-04 00:05:48

标签: .net multithreading .net-4.0 semaphore

当使用带有取消令牌的SemaphorSlim时,我应该如何构建try / finally,以便正确处理OperationCancelledException?在选项A中,取消令牌源会抛出OperationCancelledException但不会调用Release()。在选项B中,取消令牌源会抛出OperationCancelledException,并且DOES会调用Release()。

// option A:
_semaphorSlim.Wait( _cancellationTokenSource.Token );
try
{
     // do work here
}
finally
{
     _semaphorSlim.Release();
}


// option B:
try
{
     _semaphorSlim.Wait( _cancellationTokenSource.Token );
     // do work here
}
finally
{
     _semaphorSlim.Release();
}

2 个答案:

答案 0 :(得分:7)

选项A在这里更正确。取消时,您不需要Release SemaphoreSlim,因为您从未实际获取并增加其计数。因此,除非Wait调用实际成功,否则您不希望发布。

从此MSDN Page on using Semaphore and SemaphoreSlim

  

程序员有责任确保线程不会释放信号量太多次。例如,假设信号量的最大计数为2,并且线程A和线程B都进入信号量。如果线程B中的编程错误导致它调用Release两次,则两个调用都会成功。信号量的计数已满,当线程A最终调用Release时,将抛出SemaphoreFullException。

答案 1 :(得分:0)

- 对于迟到的回复感到抱歉,希望它可能对某人有所帮助。 由于我们无法保证取消的时刻以及此代码可能被命中时我们需要使用选项A.然后在finally子句中检查是否已使用取消令牌。如果已使用,则释放信号量。