Может Monitor.Enter сгенерировать исключение? - PullRequest
5 голосов
/ 12 января 2012

Может Monitor.Enter выбросить любое исключение.Я делаю обзор кода и нахожу, что Monitor.Enter перед попыткой блокировки.Видите ли вы какие-либо проблемы с в?

Monitor.Enter(...)
try
{
    ...
}
finally
{
    Monitor.Exit(..)
}

Ответы [ 4 ]

13 голосов
/ 12 января 2012

Это правильный шаблон, независимо от того, Enter() бросает (может бросить) или нет.

Только после успешного вызова Enter() ваш код отвечает за вызов Exit().

Предположим, что звонок на Enter() не удался. Тогда вызывать соответствующий Exit() просто неправильно, это усугубит ситуацию. Так что Enter() должен быть вне (перед) блока try.

10 голосов
/ 13 января 2012

Комментарий Ганса Пассанта, конечно, правильный.Если Monitor.Enter бросает до блокировки, то вы не хотите, чтобы наконец-то запустился.Если он выдает после блокировки, и после , попытка вводится, тогда блокировка снимается.(Подробнее об этом позже.) Но если бросок произойдет после того, как будет снята блокировка, но за до попытка введена, блокировка никогда не будет очищена.

Эторедкая, но возможная ситуация.

В C # 4 мы изменили кодовый код оператора блокировки, чтобы ввод монитора был внутри попытки.Это гарантирует, что блокировка всегда снимается, если что-то срабатывает после того, как блокировка снята.Тем не менее, обратите внимание, что это все равно может быть неправильно .Если что-то выбрасывается после взятия блокировки, то , независимо от неатомарной мутации, которую защищает блокировка, может быть наполовину завершено , и тогда блок finally разблокирует блокировку и разрешит доступ к несогласованному состоянию!Фундаментальная проблема здесь заключается в том, что вы не должны бросать блокировку в первую очередь.

См. мою статью о проблеме для дальнейшего обсуждения.

1 голос
/ 12 января 2012

Monitor.Enter может выдать как минимум следующие исключения

  • ArgumentNullException для параметра: null
  • ThreadInterruptedException, если поток, выполняющий Enter, вызвал метод Interrupt.
0 голосов
/ 12 января 2012

Если он получает блокировку, то нет.

Но между блоком Monitor.Enter и try может возникнуть исключение.

Рекомендуемый метод - новый Введите метод, новый в .NET 4:

public static void Enter( obj, ref bool lockTaken )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...