Есть ли способ определить, заблокирован ли объект? - PullRequest
46 голосов
/ 19 августа 2009

Есть ли способ определить, заблокирован ли объект в C #? У меня незавидная позиция, благодаря дизайну, когда я читаю из очереди внутри класса, и мне нужно выбросить содержимое в коллекцию в классе. Но эта коллекция также доступна для чтения / записи из интерфейса вне класса. Поэтому, очевидно, может быть случай, когда коллекция записывается, в то же время, когда я хочу писать в нее.

Я мог бы запрограммировать его, скажем, с использованием делегата, но это было бы ужасно.

Ответы [ 5 ]

42 голосов
/ 19 августа 2009

Вы всегда можете вызвать статический TryEnter метод для Monitor класса , используя значение 0 для ожидаемого значения. Если он заблокирован, то вызов вернет false.

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

Как правило, плохой практикой является использование объекта, доступ к которому синхронизируется, в качестве объекта для блокировки (слишком много внутренней информации об объекте).

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

11 голосов
/ 19 августа 2009

Monitor.TryEnter будет успешным, если объект не заблокирован, и вернет false, если в этот самый момент объект заблокирован. Однако обратите внимание, что здесь есть неявная гонка: экземпляр, который возвращает этот метод, может больше не блокировать объект.

7 голосов
/ 21 мая 2010

Я не уверен, что статический вызов TryEnter со временем 0 гарантирует, что блокировка не будет получена, если она доступна. Решение, которое я сделал, чтобы проверить в режиме отладки, что переменная синхронизации была заблокирована, использовало следующее:

#if DEBUG
// Make sure we're inside a lock of the SyncRoot by trying to lock it.
// If we're able to lock it, that means that it wasn't locked in the first
// place.  Afterwards, we release the lock if we had obtained it.
bool acquired = false;
try
{
    acquired = Monitor.TryEnter(SyncRoot);
}
finally
{
    if (acquired)
    {
        Monitor.Exit(SyncRoot);
    }
}
Debug.Assert(acquired == false, "The SyncRoot is not locked.");
#endif
6 голосов
/ 19 августа 2009

В настоящее время вы можете вызвать Monitor.TryEnter, чтобы проверить, заблокирован ли объект или нет.

В .NET 4.0 CLR команда собирается добавить «API проверки блокировки»

Вот цитата из Рик Байерс Статья:

проверка замка
Мы добавляем несколько простых API в ICorDebug, которые позволяют вам исследовать управляемые блокировки (мониторы). Например, если поток заблокирован в ожидании блокировки, вы можете найти, какой другой поток в данный момент удерживает блокировку (и есть ли время ожидания).

Итак, с помощью этого API вы сможете проверить:
1) Какой объект держит замок?
2) Кто этого ждет?

Надеюсь, это поможет.

4 голосов
/ 18 ноября 2016

Monitor.IsEntered

Определяет, удерживает ли текущий поток блокировку указанного объекта.
Доступна с 4.5

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...