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

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

问题描述

为了引发事件,我们使用 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 变为 null 的可能性很小.然而,MulticastDelagates 是不可变的,所以如果你首先分配一个变量,对变量进行空检查并通过它调用,你可以安全地避免这种情况(自我插件:我写了一个 不久前关于此的博文).

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 的保护,但事件可能会在事件侦听器与事件分离后调用.这只是以最优雅的方式处理的事情.

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天全站免登陆