安全地提升事件线程 - 最佳实践 [英] Raise event thread safely - best practice

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

问题描述

为了提出一个事件,我们使用一个方法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);
    }
}

但是这个有什么区别? p>

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 成为 null 。但是, MulticastDelagate 是不可变的,所以如果你首先分配一个变量,对该变量进行空检查并通过它调用,你是安全的(自我插件:我写了关于此的博客文章 a之前)。

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

虽然有硬币的背面,如果您使用临时变量方法,则您的代码将受到 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天全站免登陆