Thern
Thern

Reputation: 1059

Event is null after having it checked for being not-null

Suppose there is the following code snippet (I am using .NET 4.0):

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

When running a fairly large program containing this (simplified) method, in rare cases I encounter a NullReferenceException from MyEvent(). The debugger tells me that MyEvent is null even though I just checked that it is not null. What is going on here?

Now some people might immediately say: "Of course, if you have a multithreaded application, another thread might unregister myEvent before those irrelevant calculations are finished and - Boom! - you have a NullReferenceException!"

That is surely true, but before I venture deeper into the darkness of multithreading (since it is a very rare error, I often have to wait days for it to occur again), I need to know if there are any other possibilities for this to happen?

Specifically: Does an event being null after a successful non-null check necessarily mean that another thread has unregistered the event?

(Another option I could imagine is the external unmanaged code which is executed by the program as well and which has already caused some data access violations before. Is it possible that some operation there is causing the pointer to MyEvent to be overwritten? Or should this be impossible since the code snippet is part of the managed code? I am too inexperienced with that stuff to be able to tell.)

If you say now: Hey, why do you not log all register/unregister processes and check what is going on yourself: You are right. I am already on it. But as I said, with a bit bad luck it can take a week before I get an answer, and I want to check out other possibilities as well in the meantime.

Update

Things get stranger. The assumption was correct, the debugger shows that MyEvent is indeed null when being called. So I did what was recommended here and replaced

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

with

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

But this still yields a NullReferenceException. Debugging shows that MyEvent is again null when handler() is called, but handler itself is not. How can a NullReferenceException be evoked if the object is not even null?

Upvotes: 2

Views: 94

Answers (1)

Philippe Paré
Philippe Paré

Reputation: 4418

You have two options. If you're working in C# 6.0 or higher, you can use the null coalescing operator. Behind the scenes, it'll prevent this problem from happening. Here's how:

MyEvent?.Invoke();

The other option is useful if you're not using C# 6.0. Just store it in a variable first, check the variable, and then invoke it using the local variable, like this:

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

Upvotes: 3

Related Questions