事件在检查不确定后是无效的



假设有以下代码段(我使用的.net 4.0):

private void CauseTrouble()
{
    if (MyEvent != null)
    {
        DoSomeIrrelevantCalculations();
        MyEvent();
    }
}

在运行包含此(简化)方法的相当大的程序时,在极少数情况下,我会遇到MyEvent()的NullReferenceException。调试器告诉我,即使我只是检查它不是零的,即使我的myevent是无效的。这里发生了什么?

现在有些人可能会立即说:"当然,如果您有一个多线程应用程序,另一个线程可能会在这些无关的计算完成之前就没有注册myEvent,并且 - 繁荣!

这肯定是正确的,但是在我更深入地进入多线程的黑暗之前(由于这是一个非常罕见的错误,我经常必须等待几天才能再次发生),我需要知道是否还有其他可能性为此发生?

特别是:成功的非空检查后,事件是否为null 必然是意味着另一个线程未注册事件?

(我可以想象的另一个选项是该程序也执行的外部非托管代码,并且以前已经造成了一些数据访问。是否有可能在那里的某些操作导致指向MyEvent的指针被覆盖?还是由于代码段是托管代码的一部分,这是不可能的吗?我对这些内容没有经验。)

如果您现在说:嘿,为什么您不记录所有注册/解放流程并检查自己发生的事情:您是对的。我已经在上面了。但是正如我所说,运气不好,可能需要一个星期才能得到答案,并且我也想在此期间检查其他可能性。

update

事情变得陌生。假设是正确的,调试器表明,在被调用时,MyEvent确实是无效的。所以我做了这里推荐的事情并取代了

if (MyEvent != null)
{
    DoSomeIrrelevantCalculations();
    MyEvent();
}

var handler = MyEvent;
if (handler != null)
{
    DoSomeIrrelevantCalculations();
    handler();
}

,但这仍然产生nullReferenceException。调试表明,当调用Handler()时,MyEvent再次为NULL,但处理程序本身不是。如果对象不为null,

如何唤起nullReference coption?

您有两个选择。如果您在C#6.0或更高版本中工作,则可以使用NULL合并操作员。在幕后,它将防止此问题发生。以下是:

MyEvent?.Invoke();

如果您不使用C#6.0,另一个选项将很有用。只需首先将其存储在变量中,检查变量,然后使用局部变量调用它,例如:

var eventHandler = MyEvent;
if (eventHandler != null)
{
    eventHandler();
}

相关内容

  • 没有找到相关文章

最新更新