安全地提高事件线程

我确信我以前见过这个,但是我想知道我应该如何安全地提出一个事件线程。

我有一个消息发送线程,看起来很像。

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));

在检查发生后,哪些确实会停止引用变为空的可能性。 我想知道如何处理委托人处置的情况(或者甚至可以?)

我是否应该只是试着抓住它,因为它可能很少会发生?

编辑

阅读答案后,我考虑让我的课程来处理这个问题 - 很快它看起来像下面的内容,但我遇到了一些问题,使得它不像我想要的那么干净 - 也许有人有一个想法如何做到这一点?

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);
            }
        }
    }
}

后一种结构将确保您不会在非Itanium体系结构中调用处理程序的空引用异常。

但是,它会导致另一个可能的问题 - 注册事件处理程序的客户机可能会在处理程序被删除后调用该处理程序。 防止这种情况的唯一方法是序列化引发事件并注册处理程序。 但是,如果你这样做,你就有潜在的僵局。

总之,有三种可能的方式可以打破 - 我按照你在这里完成的方式(和MS建议)行事,并接受事件处理程序在未注册后可能被调用。


从Eric Lippert阅读这篇文章:活动和比赛


请检查:在事件调度前检查null ...线程安全吗?

链接地址: http://www.djcxy.com/p/52933.html

上一篇: Raising an event thread safely

下一篇: Using a Strong Typed 'Sender'?