Этот код довольно грязный, но я считаю, что причина, по которой вы получаете исключение, заключается в том, что вы блокируете ссылку null
.
Когда вы делаете:
add
{
lock (ChangeEvent) { ... }
}
Компилятор на самом деле использует приватное поле , поддерживающее событие ChangeEvent
(см. похожее на поле событие ). Обратите внимание, что начальное значение этого поля null
(ему не было явно назначено начальное значение, скажем, через инициализатор поля).
Теперь, когда кто-то подписывается на событие «обтекания» (someObject.ChangeEvent += ...
) в первый раз, вызывается ваш пользовательский add
метод доступа, что приводит к попытке заблокировать объект ссылается на это поле (для блокировки на самом деле нужны некоторые данные в заголовке объекта, называемом «блоком синхронизации»). Конечно, такого объекта не существует, и именно поэтому блокировка срабатывает.
Что касается странного параметра obj
, то это параметр из Monitor.TryEnter(object obj, ref bool lockTaken)
, к которому и сводится оператор блокировки C # (предыдущие версии C # предназначались для другого метода).
Честно говоря, я бы настоятельно рекомендовал переработать весь этот кусок кода.
РЕДАКТИРОВАТЬ: Уточнил использование события обтекания.