Я уверен, что видел это раньше, но мне интересно, как я должен поднимать потоки событий - безопасно.Безопасное создание потока событий
У меня есть поток сообщений, который выглядит чем-то вроде.
while(_messages > 0){
Message msg;
// get next message
if (MessageDispatched != null)
MessageDispatched(this, new MessageDispatchedEventArgs(msg.Msg, msg.Params));
}
Я могу видеть, что это может быть для MessageDispatched
Возможное чтобы прийти нуль после проверки. из блога MS, который я видел:
var handler = MessageDispatched;
if (handler != null)
handler(this, new MessageDispatchedEventArgs(msg.Msg, msg.Params));
Который останавливает возможность обращения ссылки к нулю после проверки. Мне интересно, как обрабатывать случай, когда делегат находится (или даже если он может?)
Должен ли я просто придерживаться попытки/поймать его, так как его, вероятно, очень редко произойдет?
Редактировать
После прочтения ответов я думал сделать свой класс, чтобы справиться с этим - быстро это выглядит WHATS ниже, но я бег в нескольких вопросов, которые делают его не так чисты, как я хочу - может быть, у кого-то есть идея, как это сделать?
public class ThreadSafeEvent<TDelegate>
// where TDelegate : Delegate why is this a non allowed special case???
{
List<TDelegate> _delegates = new List<TDelegate>();
public void Subscribe(TDelegate @delegate)
{
lock (_delegates)
{
if (!_delegates.Contains(@delegate))
_delegates.Add(@delegate);
}
}
public void Unsubscibe(TDelegate @delegate)
{
lock (_delegates)
{
_delegates.Remove(@delegate);
}
}
// How to get signature from delegate?
public void Raise(params object[] _params)
{
lock (_delegates)
{
foreach (TDelegate wrappedDel in _delegates)
{
var del = wrappedDel as Delegate;
del.Method.Invoke (del.Target, _params);
}
}
}
}
Проблемы с кодом добавленным с помощью редактирования возможного тупика. Рассмотрим это: объект подписывается на ваш обработчик. В потоке A получен замок. В потоке B происходит что-то, что требует, чтобы событие было поднято. В обработчике для этого он пытается получить блокировку, удерживаемую нитью A, блокируя. Затем поток A пытается зарегистрировать обработчик события, что приводит к тупиковой ситуации (каждый поток содержит блокировку, которую ожидает другой). ИМХО, это хуже, чем любая другая проблема (NullRef ничего не делает, или фантомное событие из рекомендованного MS). –