2009-10-16 3 views
3

Я столкнулся со следующей ситуацией (. C#/Net здесь, но я думаю, что это общая проблема):Отправитель событие получает удалялись в кодексе обработчика событий клиента

  • Некоторые из наших типов объектов (которые являются коллекции) являются одноразовыми типами (IDisposable на C#, который позволяет клиентам явно указывать объект «вам больше не нужен, освободите все ваши ресурсы»)
  • Эти коллекционные пожарные события («о, мой, смотри, кто-то просто добавил/удалил»/изменил элемент ').
  • Во время запуска кода обработчика событий клиента этот код решает удалить объект, который только что отправил событие (что, семантически, является правильным действием, например: теперь коллекция не содержит объект интереса для меня больше, поэтому я избавлюсь от него).

Это, конечно, наносит ущерб отправляющим объектам.

В настоящее время «решение» заключается в защите (т.е. запретить) размещени в то время как события увольняют:

private bool m_AllowDisposal; 

private void MeFiringEvents() 
{ 
    m_AllowDisposal = false; 

    // Fire event 
    if (m_MyEventHandlers != null) 
    { 
     m_MyEventHandlers(...); 
    } 

    m_AllowDisposal = true; 
} 

public void IDisposable.Dispose() 
{ 
    if (m_AllowDisposal) 
    { 
     // Dispose resources, set members to null, etc 
    } 
} 

Как вы можете видеть, это не реальное решение, поскольку распоряжение для отправителя мероприятия эффективно блокируется во время обработки кода клиента.

Любое другое решение, которое я мог придумать бы по линии

  • После каждого выстрела событий, проверить, является ли удаление (или любой другой «плохой» модификация объекта) произошло в обработчик событий клиента код.
  • Выйдите из кода отправителя (который может быть глубоко вложен до тех пор, пока он не достигнет срабатывания события) защитным способом.

Интересно, что я не нашел полезной информации по этой теме в сети, хотя это похоже на общий showstopper.

Возможно, у вас есть идея.

Спасибо за ваше внимание,

Christian

+0

«Это, конечно, наносит ущерб отправляющим объектам». Почему конечно"? Вы не можете это исправить? – Henrik

+0

Ну, если сразу после вызова обработчиков событий вашего клиента все ваши переменные-члены были установлены в нуль (по вашему собственному методу размещения), это означает бесконечность if (member! = Null), что кажется довольно неудобным. – 7enderhead

ответ

1

Кажется мне, что есть много вещей, которые происходят в то же время сохранить надлежащий учет.

Я бы попытался отделить проблему «избавления от объектов», например, добавить объекты, которые могут быть размещены в диспетчере очереди/удаления, который будет обрабатывать (вызывать Dispose on) предметы в более безопасном и более безопасном режиме разработанный/понятный и детерминированный способ. Во всяком случае, это должно помочь в отладке проблемы.

+0

Внешний диспетчер Dispose может быть хорошей идеей (лучше попытаться справиться с этим в самом удаленном объекте). Нахождение хорошего момента во время выполнения, чтобы Dispose Manager выполнял свою работу, может быть проблемой, так как наш код вызывается в самих событиях, и мы однопоточны. Хм, мне нужно подумать об этой проблеме времени, но это, безусловно, хорошая отправная точка для того, чтобы иметь один «реестр одноразовых вещей, который тогда не мог быть настроен». Спасибо всем за ваши предложения! Cheers, Christian – 7enderhead

0

Вы можете рассмотреть другой подход, если вам нужен только один слушатель, который должен располагать объект, возможно, простой обратный вызов (реализация шаблона Begin/End в .NET).

Устранение отправителя события не всегда семантически соответствует: объект, создавший коллекцию (или инициировавший ее создание), должен нести ответственность за ее удаление, а не за любого наблюдателя.

+0

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

+0

Невозможно ли создать код, создающий коллекцию/наблюдателя, чтобы избавиться от него? –

+0

Я заберу идею _NT менеджера Dispose, которая может выполнять свою работу в собственном объекте. – 7enderhead