开发者

More on events and thread safety

开发者 https://www.devze.com 2023-02-27 03:06 出处:网络
I discovered this post on StackOverflow about events and races which helped me immensely - C# Events and Thread Safety

I discovered this post on StackOverflow about events and races which helped me immensely -

C# Events and Thread Safety

The key statement here is that 'Event handlers are required to be robust in the face of being called even after the event has been unsubscribed'

I take this to mean that when you subscribe to an event, you must be prepared for that event to be raised even after you have unsubscribed to it, and do some sort of check to see whether the event should be processed.

This could be something as simple (and ugly) as

bool _acceptEvents;

// event handler
void LoggedIn(object sender, EventAr开发者_StackOverflow社区gs a)
{
    if (!_acceptEvents) return;

    Evt("Now logged in");
}

// code to unsubscribe to event
_acceptEvents = false;
_parent.LoggedIn -= new LoggedInEventHandler(LoggedIn);

Now obviously the above code is god awful to look at, but it serves the purpose required.

My question is, what would be a more elegant way of doing this? What is the typical way of handling this situation?

I had thought perhaps you could do

if (!_parent.LoggedIn.Contains(myhandler)) return;

but I tried, and I guess events are designed in a way to prevent you from seeing other subscribers.

What do you think?

Thanks


imho it's a non-existing problem. Have you ever had any code that have generated a bug (or will generate a bug) because an event was called after it was unsubscribed?


Indeed events encapsulate a multicast delegate's invocation list so you can not directly remove your subscription.

The main reason that a handler can be called after unregistering (even if you could remove your subscription from the list) is that the event owner could have made a copy of the invocation list.

Look at this code:

var ev = TheEvent;
if(ev != null)
{
    ev(this, EventArgs.Empty);
}

The first line creates a copy of the invocation list to prevent from raising the event in the 4th line on an empty list (and thereby protecting you from a null reference exception)

So if you unregister between lines 1 and 4 your handler will still be invoked because a reference to it has been copied in ev.

0

精彩评论

暂无评论...
验证码 换一张
取 消