Переопределение C # Monitor.Enter и Monitor.Exit - PullRequest
2 голосов
/ 22 февраля 2011

Я работаю над каким-то большим многопоточным проектом, теперь вчера у меня возникла тупиковая ситуация (мой первый в истории), и я отследил ее, добавив Console.WriteLine ("FunctionName: Lock on VariableName") и Console.WriteLine («Имя_функции: разблокировка имени-переменной»). Добавление всего этого было довольно сложной работой.

Прежде всего, в программе есть основной цикл, который выполняется 2 раза в секунду, и этот цикл заставляет некоторые другие потоки завершить свою работу после обработки основного цикла. Теперь произошло то, что у меня был один поток в состоянии ожидания для пульсации, когда он был импульсным, он вызвал другой метод, который также ожидал, чтобы получить импульс, но импульс уже произошел, и поток не будет пульсировать снова, пока действие фактически завершено.

Теперь я хочу переопределить функции Monitor.Enter и Monitor.Exit, не заключая их в класс.
Я много слышал об Reflection, но я не знаю, как применить его для этой цели, я знаю, что самый простой способ достичь всего этого - просто использовать класс-обертку, но тогда ключевое слово lock больше не будет работать, и мне придется преобразовать все блокировки в Monitor.Enter try {} finally {Monitor.Exit}, это огромный объем работы.

Итак, мой вопрос: как переопределить функции Monitor.Enter и Monitor.Exit, сохраняя доступ к базовой функции для фактической блокировки?
И если это невозможно: как переопределить оператор блокировки для вызова моего класса-оболочки вместо функций Monitor.Enter и Monitor.Exit?

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

Ответы [ 3 ]

3 голосов
/ 22 февраля 2011

Похоже, вы ищете помощников блокировки.MiscUtil от Jon Skeet имеет следующее: http://www.yoda.arachsys.com/csharp/miscutil/usage/locking.html

Идея состоит в том, что вы заменяете свои операторы lock на using и таким образом сохраняете структуру try-finally:

class Example
{
    SyncLock padlock = new SyncLock();

    void Method1
    {
        using (padlock.Lock())
        {
            // Now own the padlock
        }
    }      

    void Method2
    {
        using (padlock.Lock())
        {
            // Now own the padlock
        }
    }
}

Что касается предотвращения взаимоблокировок, библиотека предлагает специализированную упорядоченную блокировку:

class Example
{
    OrderedLock inner = new OrderedLock("Inner");
    OrderedLock outer = new OrderedLock("Outer");

    Example()
    {
        outer.InnerLock = inner;
    }
}

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

2 голосов
/ 22 февраля 2011

Не делай этого!Это звучит как чокнутый; -)

Заседание возникает, когда все 2 (или более) потока ожидают одновременного удержания 2 (или более) блокировок.И каждый поток получает блокировку и ждет другого.

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

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

0 голосов
/ 22 февраля 2011

Это очень плохая идея. Мне никогда не приходилось переопределять Monitor.Enter / Exit или блокировку, чтобы преодолеть тупик. Пожалуйста, рассмотрите возможность изменения вашего кода!
Например, используйте ManualResetEvent для пульсации.

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