Должен mutex.WaitOne () внутри или перед блоком try / finally - PullRequest
3 голосов
/ 30 апреля 2010

Мне было интересно, какой из следующих вариантов был предложенным шаблоном при использовании Mutex (или семафоров или ReadWriteLockSlims и т. Д.).

Должна ли начальная блокировка происходить внутри или снаружи оператора try? Это неважно?

_mutex.WaitOne()
try
{
 // critical code
}
finally
{
  _mutex.ReleaseMutex();
}

или

try
{
  _mutex.WaitOne()
 // critical code
}
finally
{
  _mutex.ReleaseMutex();
}

Ответы [ 3 ]

2 голосов
/ 30 апреля 2010

Единственный способ, которым они могут отличаться, - это если исключение произошло после WaitOne, но до начала попытки в примере 1 или после начала попытки, но до WaitOne в примере 2. В первом случае мьютекс не будет освобожден и во втором случае может быть предпринята попытка освобождения, даже если ожидание не ожидается. Исключением должно быть что-то серьезное, например ThreadAbortException, чтобы оно возникло в любом месте. Однако, если мьютекс содержится в блоке using, проблем не будет.

РЕДАКТИРОВАТЬ: после прочтения поста Эрика на эту тему, на который ссылался Оливер, я думаю, что даже с использованием блока, ситуация не идеальна, и что просто использование второй версии, как предлагает Оливер, - ваш лучший вариант.

1 голос
/ 30 апреля 2010

Может быть, это другое. Посмотрите на эти сообщения от Эрика:

Вкратце: Представьте, что между оператором mutex.WaitOne() и try происходит исключение. Вы оставите этот кусок кода без вызова _mutex.ReleaseMutex().

Так что возьмите ваш второй кусок кода, чтобы убедиться, что все работает как положено.

0 голосов
/ 30 апреля 2010

Если вы не используете мьютекс для межпроцессной синхронизации.

См. Ответ на этот вопрос C # - Проблемы с блокировкой Mutex

Тогда это будет безопаснее:

private static object _syncLock = new object();

public void RunCriticalCode()
{
    lock (_syncLock)
    {
        // critical code
    }
}
...