- PVSM.RU - https://www.pvsm.ru -
Данная заметка — попытка вставить свои 5 копеек на тему, затронутую в статье [1] пользователя KumoKairo [2].
Не далее как год назад я столкнулся с подобной проблемой — необходимо было рассылать события клиентам из WCF-службы, причем один подписчик события не должен страдать от того, что другой подписчик события в момент генерации этого события отвалился.
Как и автор упомянутой заметки, я пошел смотреть, что же такого умного написано на эту тему, и набрел вот на эту публикацию [3]. Пришел к выводу, что строго говоря, задача не решается, то есть мы никак не сможем избежать случайного вызова обработчика событий от того подписчика, который отписался в «неудобный» момент. Но есть неплохой способ избежать последствий такой ситуации.
Примерный код приведен ниже (мое решение в продуктовом коде было несколько более корявым):
delegate void SomeEventHandler(object sender, EventArgs a);
class SampleHandlers
{
SomeEventHandler someEvent;
Dictionary<SomeEventHandler, SomeEventHandler> m_actions = new Dictionary<SomeEventHandler, SomeEventHandler>();
readonly object someEventLock = new object();
//Подписка/отписка от события
public event SomeEventHandler SomeEvent
{
add
{
lock (someEventLock)
{
SomeEventHandler h = new SomeEventHandler((o, a) =>
{
try { value(o,a); }
catch
{
//тут как-то это обрабатываем. Я или просто пишу в лог, или удаляю
//обработчик (что на самом деле непросто), - в зависимости от типа исключения.
}
});
someEvent += h;
m_actions[value] = h;
}
}
remove
{
lock (someEventLock)
{
try
{
SomeEventHandler h = m_actions[value];
m_actions.Remove(value);
someEvent -= h;
}
catch
{ /*тут как-то это обрабатываем, я тут просто пишу в лог*/}
}
}
}
//Генерация события:
protected virtual void OnSomeEvent(EventArgs e)
{
SomeEventHandler handler;
lock (someEventLock)
{
handler = someEvent;
}
if (handler != null)
{
handler(this, e);
}
}
}
Как видно, идея просто в том, чтобы вызов каждого клиентского обработчика «на всякий пожарный» обернуть в «свой» блок try-catch. Ну и для нормального «отписывания» пришлось немного нагородить — добавить словарь соответствия между клиентскими обработчиками и нашими. Мне кажется, описанный способ имеет право на существование. Если можно что-то похожее реализовать легче/правильнее, я буду рад ссылкам и комментариям.
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/pesochnitsa/72256
Ссылки в тексте:
[1] статье: http://habrahabr.ru/post/240385/
[2] KumoKairo: http://habrahabr.ru/users/kumokairo/
[3] эту публикацию: http://www.codeproject.com/Articles/37474/Threadsafe-Events
Нажмите здесь для печати.