Why copy an event handler into another variable - c#

In an example, I find this code:
public event EventHandler ThresholdReached;
protected virtual void OnThresholdReached(EventArgs e)
{
EventHandler handler = ThresholdReached;
if (handler != null)
handler(this, e);
}
I would like to understand the reason for the line:
EventHandler handler = ThresholdReached;
Can we not just do it this way:
public event EventHandler ThresholdReached;
protected virtual void OnThresholdReached(EventArgs e)
{
if (ThresholdReached != null)
ThresholdReached(this, e);
}
Are there some advantages/disadvantages to either way of doing it?

The problem is that between this line
if (ThresholdReached != null)
and this line
ThresholdReached(this, e);
a different thread could have removed the handlers from the ThresholdReached event. So it would be null and an exception would be thrown.
By storing the value in a local variable, you make the call thread-safe.
Since C# 6 you can shorten the code to this
ThresholdReached?.Invoke(this, e);
Now the compiler takes care of storing the value in a temporary variable.

There's a theoretical risk of a thread race in the second version where someone unsubscribes the event between the check and the invoke, causing a NullReferenceException in the invoke step. Capturing the value into a local and testing/invoking that prevents this. However, perhaps use the third version, possible with C# 6 or above (thanks #Cid):
ThresholdReached?.Invoke(this, e);
This is basically a short-hand version of the first version - all the safety, but now with terseness.

Related

logic within c# OnEventReached method

Can someone please explain me the importance of below statement while raising an event.
EventHandler<ThresholdReachedEventArgs> handler = ThresholdReached;
As we are simply assigning the Threshold event to handler, why can't we just simply call like ThresholdReached(this, e)
protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
{
EventHandler<ThresholdReachedEventArgs> handler = ThresholdReached;
if (handler != null)
{
handler(this, e);
}
}
public event EventHandler<ThresholdReachedEventArgs> ThresholdReached;
Having this first line protects from race conditions in multi threaded application.
Imagine if some other thread unsubscribed from event just after you checked if it is not null.
And checking for null is necessary because event without any handlers is null and you would get NullReferenceException by calling such event.
So to be precise.
This code does not check for null and may throw NullReferenceException:
protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
{
ThresholdReached(this, e);
}
This is dangerous due to possible race condition and possibly may also throw an exception:
protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
{
if (ThresholdReached != null)
ThresholdReached(this, e);
}
EDIT (to better explain behavior of local variable):
Having this assignment creates a local copy of the event maintaining its state. So if any thread unsubscribes from event local copy remains the same throughout the rest of the method call. In other words the delegate behaves like copying a structure not like copying a reference.
Below code would print text:
// let's assume ThresholdReached is null
ThresholdReached += MyHandler;
EventHandler<ThresholdReachedEventArgs> localCopy = ThresholdReached ;
ThresholdReached -= Program_SthEvent;
if (localCopy != null)
Console.WriteLine("we have a copy!");
Notice how localCopy remains state and value;

C# event handlers : when are the subscribers invoked?

After doing some reading here is what I think is happening, and I am just looking for confirmation or correction.
The samples below will be using anonymous lambdas for brevity, obviously doing that you would lose the ability to unsubscribe.
MyEvent += (sender, args) => {Console.WriteLine("One")};
MyEvent += (sender, args) => {Console.WriteLine("Two")};
MyEvent += (sender, args) => {Console.WriteLine("Three")};
With the subscribers in place, we would invoke the Event:
var handler = MyEvent;
if(handler != null){
handler(this, EventArgs.Empty) // <-- Interested in this moment
}
So here is where I will need correcting/clarification/guidance. As I understand it, what invoking handler is effectively doing is (I understand it's not doing EXACTLY this, this is for illustrative purposes only).
foreach(var subscriber in self){
subscriber(sender, args);
}
I'm explicitly not talking about using this with BeginInvoke. So what happens is basically invoking the handler causes the handler to loop through all of it's subscribers in some undefined order and invoke them passing the appropriate args from the invoking thread (in this example, again not talking about BeginInvoke)
Put another way, handler(this, EventArgs.Empty) is basically just doing this immediately, on the invoking thread:
anonymous1(..., ...)
anonymous2(..., ...)
anonymous3(..., ...)
Modifying the above slightly:
var handler = MyEvent;
if(handler != null){
handler(this, EventArgs.Empty) // <-- Interested in this moment
}
Console.WriteLine("Done Invoking Subscribers");
We can always expect the output to be (since none of our subscribers are async and we are not using BeginInvoke):
// some undefined order of the following 3 lines:
One
Two
Three
// Always followed by
Done Invoking Subscribers
Generally speaking, do I have this idea right?
Yes
Sorry to be that direct but the simple answer is yes, that's how it works.

C# events initialisation

Consider the "application" where an object (Thrower) is throwing a ball to another object (Receiver). The event (BallIsThrowed) happens when the ball is thrown.
Here are the 2 classes :
then the entry point :
And finally the methods pointed by the delegate when events are fired :
This is working well.
Now I want to comment this line :
because I want to say that the ball was not thrown.
The result is a null Exception :
This is normal because at this point BallIsThrowed is null
To solve this, I initilise my event :
But then my problem is that my code is never taking the event when I decomment "receiver.Register(thrower)"
My questions are :
How can I have the 2 method EventMethod fired ?
The best practice way to fire an event looks like this:
EventHandler ballIsThrowed = BallIsThrowed;
if (ballIsThrowed != null)
{
ballIsThrowed(this, EventArgs.Empty);
}
The reason for the temporary variable is to prevent race conditions between the null check and the execution.
Bear with me: you are setting an event handler to BallIsThrowed, then you use IthrowTheBall() to actually trigger the event, with this code:
BallIsThrowed(this, EventArgs.Empty);
When you try to call an event handler, in this case the BallIsThrowed, it must exists or it will throw a NullReferenceException. So, in order for this to work, it must exists an event handler BallIsThrowed. It actually does, until you comment this line:
//BallIsThrowed += new EventHandler(method.EventMethod2);
So basically you need to verify if the EventHandler exists before firing it:
if (BallIsThrowed != null)
BallIsThrowed(this, EventArgs.Empty);
Another (more elegant, if you ask me) way of doing this is:
(BallIsThrowed??delegate{})(this, EventArgs.Empty);
Compact, thread safe...
Two things that need to be corrected:
In your Event Invoker, check EventHandler != null because you dont know if anyone registered to your handler.
var ballThrown = BallIsThrowed;
if (ballThrown != null)
{
ballThrown(this, EventArgs.Empty);
}
For general knowledge, In order to register more then one delegate to your
EventHandler, dont register it via the = operator, but via the
+= operator, meaning you want to append a new delegate:
public void IThrowTheBall()
{
// Do stuff
// You dont have to register this delegate, you can append it to the current
// delegates already registered
BallIsThrowed += method.EventMethod1;
}

Why is an additional if statement to check if an event is null before invoking it?

I am going through this code below:
public delegate void PersonArrivedEventHandler(string personName, byte[] personId);
public class SCLib
{
public event personArrivedEventHandler personrrived;
public SCLib()
{
// Simulate that the person arrived after 2000 milli-seconds.
Task.Run(() =>
{
System.Threading.Thread.Sleep(2000);
OnPersonArrived("personName", new byte[] { 0x20, 0x21, 0x22 });
});
}
protected virtual void OnPersonArrived(string smartCardReaderName, byte[] smartCardId)
{
if (this.personArrived != null)
{
PersonArrived(personName, personId);
}
}
}
But, I don't know what is the significance of this line,
if (this.personArrived != null).
Why is this check done here? Is there any significance of the if statement here? I removed this line and ran the program and everything works as before.
Thanks.
If the event is not subscribed by the consumer of the class then invoking the event would raise exception as PersonArrived is null if not subscribed.
If you use an event which you have not assign a handler it will generate an exception because it is null, so you need to check it before launch the event.
Because it will be null if no delegates are attached to the event. If you try to invoke such a null event you will get the standard NullReferenceException.
'Events' are subscribe by class object using add handler.
SCLibObject.personrrived += new personArrivedEventHandler(somemethod)
If class object is not subscribe the event then you will get NullReferenceException. So before calling events check if it is null or not.
In a multi-threading application you should store the eventhandlers in a local variable before invoking. See this SO answer, this blog post from Eric Lippert and this SO answer for more details.
void SomeEventInvoke(object sender, EventArgs args) {
EventHandler ev = SomeEvent;
if (ev != null) ev(sender, args);
}

.NET: Is creating new EventArgs every time the event fires a good practice?

For example, I have a base event publishing method:
protected virtual OnSomeEvent(EventArgs e)
{
var handler = SomeEvent;
if (handler != null)
{
handler(this, e);
// handler(this, new EventArgs());// EDIT: Yes it should be
// handler(this, e),
// ignore this one :D
}
}
For a derived class that overrides OnSomeEvent and raises an additional event when it fires:
protected override OnSomeEvent(EventArgs e)
{
base.OnSomeEvent(e);
if (ExtendedEvent != null)
{
OnExtendedEvent(e);
}
}
protected void OnExtendedEvent(EventArgs e)
{
// some stuff done
// new information the ExtendedEventArgs object needs
// is not available until this point
ExtendedEvent(this, new ExtendedEventArgs(someStuff, someOtherStuff));
}
And if derivation goes on like this, it will create a new derived EventArgs for each generation of derived class that requires it. However it seems various derivations of EventArgs on the .NET framework are not designed to be mutable (no setters), this discourages an object from keeping a single instance of EventArgs and modify it as it goes.
So every time an event like this fires, it will re-allocate memory for all involved EventArgs objects. In a graphic intense application where an event can be triggered dozens of times per second (such as OnPaint event on a control), is this really a good practice?
Should I make some changes to OnExtendedEvent() and make ExtendedEventArgs mutable so the following is possible?
protected ExtendedEventArgs extendedArgs = ExtendedEventArgs.Empty;
protected void OnExtendedEvent(EventArgs e)
{
// some stuff done
// new information the ExtendedEventArgs object needs
// is not available until this point
extendedArgs.someProperty1 = someStuff;
extendedArgs.someProperty2 = someOtherStuff;
ExtendedEvent(this, extendedArgs);
}
EDIT: Fixed the example code, should be clearer now.
First off, why take an EventArgs argument to your firing method if you are just ignoring it anyway? That is the real waste, but the resource consumption is less problematic than the lie that your method is telling its callers. Just pass the argument on through, your firing method likely will not have relevant info accessible to create the EventArgs object anyway:
protected virtual OnSomeEvent(EventArgs e)
{
var handler = SomeEvent;
if (handler != null)
{
handler(this, e);
}
}
So, now that we have that straight, if your EventArgs object has no meaningful information to tell your subscribers, just use EventArgs.Empty, that's what it is there for. You could follow the same pattern for your custom EventArgs classes, but honestly, you are worrying about nothing. Creating EventArgs objects will never be a bottleneck in your application, and if it is, you have design problems.
I would create a new immutable object each time it is fired, as there are values in the event arguments.
The main reason is the what would happen if a new event is fired again while an existing event is being handled?
This will possibly happen in multi-threaded applications but may even happen on a single thread as shown by the following example:
First event is fired with the following values:
extendedArgs.someProperty1 = "Fire 1";
extendedArgs.someProperty2 = "Fire 1 Other Stuff";
Then somehow the first event handler does something causes the event to be fired again with the following arguments:
extendedArgs.someProperty1 = "Fire 2";
extendedArgs.someProperty2 = "Fire 2 Other Stuff";
All the event handlers are for the second event are processed, and now we are back to processing the rest of the event handlers for the first event.
Now since the same object is used all the event handlers for the first event will now be have "Fire 2" as their someProperty1, as the second event overwrote the values.
As #nobugz mentioned don't be afraid to create short-lived garbage.
I'm a little confused by your OnExtendedEvent code - are you meaning to redispatch the event as a SomeEvent?
When a client adds an event handler, they expect they are able to remove the event handler while handling the event, like this:
someObject.SomeEvent += OnSomeEvent;
// ...
private void OnSomeEvent(object sender, EventArgs e)
{
someObject.SomeEvent -= OnSomeEvent;
}
If you do not follow the standard dispatching practice, this code will throw an Exception very much to the surprise of the person using your code.

Categories