Соединение объекта

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

Мне кажется, что Вы могли использовать любой объект для этого, включая само событие как объект блокирования. Почему выделяют новый объект, который ничего не делает? Мое понимание - то, что вызов блокировки () на объекте на самом деле не изменяет сам объект, и при этом это на самом деле не блокирует его от того, чтобы быть используемым, это просто используется в качестве заполнителя для нескольких операторов блокировки к привязке на.

public class Shape : IDrawingObject, IShape
{
    // Create an event for each interface event
    event EventHandler PreDrawEvent;
    event EventHandler PostDrawEvent;

    object objectLock = new Object();

    // Explicit interface implementation required.
    // Associate IDrawingObject's event with
    // PreDrawEvent
    event EventHandler IDrawingObject.OnDraw
    {
        add
        {
            lock (objectLock)
            {
                PreDrawEvent += value;
            }
        }
        remove
        {
            lock (objectLock)
            {
                PreDrawEvent -= value;
            }
        }
    }
}

Таким образом, мой вопрос, это - действительно хорошая вещь сделать?

5
задан Erik Funkenbusch 5 June 2010 в 06:39
поделиться

3 ответа

включая само событие

Нет, вы не можете этого сделать. На самом деле "событие" - это просто некоторые методы доступа. Если вы имеете в виду делегат подкрепления, то это было бы очень плохо - делегаты неизменяемы: каждый раз, когда вы добавляете/удаляете подписчика, вы получаете другой делегат.

На самом деле, компилятор 4.0 теперь делает это с кодом без блокировок, используя Interlocked - возможно, стоит следовать этому подходу.

В вашем примере objectLock гарантирует, что все вызывающие (для данного экземпляра) блокируются на тот же объект, что важно - но без уродства блокировки на this (именно так работает компилятор C# used).

--

Обновление: ваш пример показывает код, необходимый до C# 4.0, доступ к field-like-event inside тип обращался непосредственно к полю: обычная блокировка field-like-event не соблюдалась. Это было изменено в C# 4.0; теперь (в C# 4.0) вы можете безопасно переписать это так:

public class Shape : IDrawingObject, IShape
{
    // Create an event for each interface event
    event EventHandler PreDrawEvent;
    event EventHandler PostDrawEvent;

    event EventHandler IDrawingObject.OnDraw
    {
        add { PreDrawEvent += value; }
        remove { PreDrawEvent -= value; }
    }
}

Все правильное поведение соблюдается.

7
ответ дан 13 December 2019 в 22:02
поделиться

Любой частный член ссылочного типа подойдет для этой работы. До тех пор, пока он является частным и никогда не будет переназначен. Это выбивает объект-делегат из общего ряда, вы определенно не хотите, чтобы блокировка не выполнила свою работу только потому, что клиентский код, который вы не контролируете, назначил обработчик события. Крайне трудно отлаживать.

Использование закрытых членов, которые выполняют другую работу, - это не то, что хорошо масштабируется. Если во время рефакторинга или отладки вы обнаружите, что вам нужно заблокировать другой участок кода, вам придется найти другой частный член. И вот тут-то все может быстро испортиться: вы можете снова выбрать тот же самый private member. Тупик стучится в дверь.

Этого не произойдет, если вы посвятите объект блокировки определенному набору общих переменных, которые нужно защитить. Позволяет также дать ему хорошее имя.

2
ответ дан 13 December 2019 в 22:02
поделиться

Рекомендуется заблокировать частное статическое поле, потому что это гарантирует, что несколько потоков, пытающихся получить доступ к блокировке параллельно, будут заблокированы. Блокировка экземпляра самого класса ( lock (this) ) или некоторого поля экземпляра может быть проблематичной, потому что если два потока вызовут метод на двух разных экземплярах объекта, они смогут одновременно ввести блокировку утверждение.

1
ответ дан 13 December 2019 в 22:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: