引发事件的线程安全 - 最佳实践 [英] Raise event thread safely - best practice

查看:131
本文介绍了引发事件的线程安全 - 最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了提升我们使用的方法的OnEventName这样一个事件:

In order to raise an event we use a method OnEventName like this:

protected virtual void OnSomethingHappened(EventArgs e) 
{
    EventHandler handler = SomethingHappened;
    if (handler != null) 
    {
        handler(this, e);
    }
}

但就是这一个区别?

But what is the difference with this one ?

protected virtual void OnSomethingHappened(EventArgs e) 
{
    if (SomethingHappened!= null) 
    {
        SomethingHappened(this, e);
    }
}

显然,第一个是线程安全的,但为什么又如何?

Apparently the first is thread-safe, but why and how ?

这是没有必要启动一个新线程?

It's not necessary to start a new thread ?

推荐答案

有一个微小的机会, SomethingHappened 变成空检查之后,但调用之前。然而, MulticastDelagate 是不变的,所以,如果你第一次分配一个变量,空检查依据的变量,并通过它调用,你是从场景安全(自我插头:我写的一<一href=\"http://softwareblog.alcedo.com/post/2010/03/12/Extension-method-for-safe-event-invocations.aspx\">blog张贴这个的前一段时间)。

There is a tiny chance that SomethingHappened becomes null after the null check but before the invocation. However, MulticastDelagates are immutable, so if you first assign a variable, null check against the variable and invoke through it, you are safe from that scenario (self plug: I wrote a blog post about this a while ago).

有是硬币虽然的背面;如果您使用临时变量的方法,你的code进行保护,防止的NullReferenceException S,但它可能是该事件会调用事件侦听器的他们已经经过从事件脱离的。这只是事情来应对可能的最得体的方式。

There is a back side of the coin though; if you use the temp variable approach, your code is protected against NullReferenceExceptions, but it could be that the event will invoke event listeners after they have been detached from the event. That is just something to deal with in the most graceful way possible.

为了解决这个问题我有一个扩展的方法,我有时使用:

In order to get around this I have an extension method that I sometimes use:

public static class EventHandlerExtensions
{
    public static void SafeInvoke<T>(this EventHandler<T> evt, object sender, T e) where T : EventArgs
    {
        if (evt != null)
        {
            evt(sender, e);
        }
    }
}

使用该方法,可以调用的事件是这样的:

Using that method, you can invoke the events like this:

protected void OnSomeEvent(EventArgs e)
{
    SomeEvent.SafeInvoke(this, e);
}

这篇关于引发事件的线程安全 - 最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆