我确定我以前见过这个,但我想知道应该如何提高事件线程安全。安全地提高事件线程
我有一个消息发送线程看起来很像。
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));
这确实会停止引用在检查发生后变为null的可能性。我想知道如何处理代理人处置的情况(或者甚至可以处理)
我应该只需要在它周围贴上一个try/catch,因为它可能很少会发生?
编辑
阅读的答案后,我考虑过让我的类来处理这个 - 很快它看起来什么下文,但我遇到了,这使得它不干净,因为我想的几个问题 - 也许有人有一个想法如何做到这一点?
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建议的方式幻影事件)更糟糕。 – 2009-11-30 01:35:44