Подтвердить что ты не робот

Есть ли способ определить, заблокирован ли объект?

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

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

4b9b3361

Ответ 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