SemaphoreSlim.Wait(CancellationToken ) правильная попытка / finally для OperationCancelledException?

#.net #multithreading #.net-4.0 #semaphore

#.net #многопоточность #.net-4.0 #семафор

Вопрос:

Как я должен структурировать попытку / finally при использовании SemaphorSlim с токеном отмены, чтобы OperationCancelledException обрабатывалось правильно? В варианте A отмена источника токена вызывает исключение OperationCancelledException, но не вызывает Release(). В варианте B отмена источника токена вызывает исключение OperationCancelledException и вызывает 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();
}
  

Ответ №1:

Вариант A здесь более правильный. Вам не нужно Release SemaphoreSlim при отмене, поскольку вы фактически никогда не получаете и не увеличиваете его количество. Таким образом, вы не хотите выпускать, если ваш Wait вызов действительно не был успешным.

С этой страницы MSDN об использовании Semaphore и SemaphoreSlim:

Ответственность программиста заключается в том, чтобы поток не освобождал семафор слишком много раз. Например, предположим, что максимальное количество семафоров равно двум, и что поток A и поток B оба входят в семафор. Если ошибка программирования в потоке B заставляет его дважды вызывать Release, оба вызова завершаются успешно. Количество в семафоре заполнено, и когда поток A в конечном итоге вызывает Release, генерируется исключение SemaphoreFullException.

Ответ №2:

-Извините за поздний ответ, надеюсь, это может кому-то помочь. Поскольку мы не можем гарантировать момент отмены и когда этот код может быть сбит, нам нужно использовать опцию A. Затем в предложении finally проверьте, использовался ли токен отмены или нет. Если оно было использовано, то не освобождайте семафор.