Есть ли способ определить, заблокирован ли объект?
Есть ли способ определить, заблокирован ли объект на С#? У меня есть незавидное положение, через дизайн, где я читаю из очереди внутри класса, и мне нужно сбрасывать содержимое в коллекцию в классе. Но эта коллекция также читается/записывается из интерфейса вне класса. Таким образом, очевидно, что может быть случай, когда сборка записывается, так же как и я хочу написать ему.
Я мог бы запрограммировать его, скажем, с помощью делегата, но это было бы уродливо.
Ответы
Ответ 1
Вы всегда можете вызвать статический метод TryEnter
на Monitor
class, используя значение 0 для ожидаемого значения. Если он заблокирован, тогда вызов вернет false.
Однако проблема заключается в том, что вам нужно убедиться, что список, который вы пытаетесь синхронизировать, блокируется сам по себе, чтобы синхронизировать доступ.
Как правило, неверно использовать объект, который синхронизируется с доступом к объекту для блокировки (выставляя слишком много внутренних деталей объекта).
Помните, что блокировка может быть на что угодно, поэтому просто вызов этого в этом списке бессмысленен, если вы не уверены, что этот список заблокирован.
Ответ 2
Monitor.TryEnter
будет успешным, если объект не заблокирован и вернет false, если в этот момент объект заблокирован. Однако обратите внимание, что здесь подразумевается неявное расследование: экземпляр, возвращаемый этим методом, объект больше не может быть заблокирован.
Ответ 3
Я не уверен, что если статический вызов 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
Ответ 4
В настоящее время вы можете вызвать Monitor.TryEnter, чтобы проверить, заблокирован ли объект или нет.
В .NET 4.0 CLR команда собирается добавить "API проверки блокировки"
Вот цитата из Рик Байерс:
проверка блокировки
Мы добавляем в ICorDebug несколько простых API, которые позволяют вам изучать управляемые блокировки (мониторы). Например, если поток заблокирован в ожидании блокировки, вы можете найти, какой другой поток в данный момент удерживает блокировку (и если есть тайм-аут).
Итак, с помощью этого API вы сможете проверить:
1) Какой объект держит замок?
2) Кто его ждет?
Надеюсь, что это поможет.
Ответ 5
Monitor.IsEntered
Определяет, поддерживает ли текущий поток блокировку указанного объекта.
Доступно с 4.5