Lets say that I have this (incomplete) class, in which I raise an event without first assigning it to a variable to make it thread-safe:
public class Test
{
public event EventHandler SomeEvent;
void OnSomeEvent(EventArgs e)
{
if (SomeEvent != null)
SomeEvent(this, e);
}
}
Would it be safe to unsubscribe an event handler from itself, or could there be any problem similar to what would happen when removing items from a collection while enumerating it?
void SomeEventHandler(object sender, EventArgs e)
{
testInstance.SomeEvent -= SomeEventHandler;
}
To clarify the other answer a bit:
Events are based on delegates (in almost all cases). Delegates are immutable. This applies to multicast delegates, too.
When invoking an event the delegate is loaded and then invoked. If the field that the delegate is stored in is modified then this does not affect the already loaded delegate.
It's therefore safe to modify the event from the handler. Those changes will not affect the currently running invocation. This is guaranteed.
All of this only applies to events backed by a delegate. C# and the CLR support custom events that could do anything at all.
It would be safe, however, just know it is not a guarantee that the code in SomeEventHandler will be executed only once. A race condition might occur if you have multithreaded code.
Edit:
Unsubscribing from an event will, behind the scenes, combine delegates to produce a list of delegates. (Lots of details can be found on that article by Jon Skeet the man himself)
Note that the event uses locks to guarantee thread safety on the Delegate combination. Once you have combined a delegate to your event, you will have a resulting list of delegates. When raising an event, however, what is not guaranteed is that the latest version of the combined delegates will be used. (see Thread-safe events) but this is unrelated to the fact the event was un-hooked from the inside of the event.
I hope my edit provides enough clarification :)
Related
I have a rather short question about anonymous event handlers:
This is the code that I have:
public void AddTestControl(Control ctrl)
{
ctrl.Disposed += (o, e) => { RemoveTestControl(ctrl); };
ctrl.SomeEvent += _Control_SomeEvent;
}
public void RemoveTestControl(Control ctrl)
{
ctrl.SomeEvent -= _Control_SomeEvent;
}
Is this code above fine, or should the code be rewritten in order to remove the Disposed Event Handler?
Something like this:
public void AddTestControl(Control ctrl)
{
ctrl.Disposed += _Control_Disposed;
ctrl.SomeEvent += _Control_SomeEvent;
}
public void RemoveTestControl(Control ctrl)
{
ctrl.Disposed -= _Control_Disposed;
ctrl.SomeEvent -= _Control_SomeEvent;
}
Generally, the only situation where you need to remove the event handlers from an object in order for it to be eligible for garbage collection is when the publisher object (the one defining the event) lives longer than the subscriber object (the one containing the event handlers). In such a situation the GC won't be able to release the subscriber when it goes out of scope since it's still being referenced by the publisher.
In this case, assuming this is WebForms or WinForms, the publisher (that is the Control object), is most likely a child object of the subscriber (probably a Page or a Form), which will be the first to go out of scope taking all its associated objects with it. Hence there's no need to remove the event handlers.
It always feels cleaner to me to unsubscribe from events, even in situations where I know the subscribers always outlive the publisher (the object raising the event): the event will never be raised again, the publisher is no longer reachable and can be collected.
Then again, how many people go to the trouble of unsubscribing every event handler in e.g. a WinForms application? The object references point from the publisher to the subscribers, not the other way around, so the publisher can be collected while the subscribers live on. It doesn't present the same danger as the opposite situation, where a long-lived publisher (e.g. a static event) can wastefully keep potentially large subscribers alive long after they could have been collected.
If you want/need to unsubscribe, then the requirement to unsubscribe the same delegate makes anonymous event handlers a bit of a pain. The Reactive Extensions solve this problem in a neat way: rather than having to remember the delegate you subscribed, subscribing returns an IDisposable which unsubscribes when disposed. Chucking all your subscriptions into a CompositeDisposable lets you unsubscribe everything with just one Dispose call.
Both codez are fine, but I like second as a matter of personal preference. It reads clearer than the first.
On top of it with the first code, there's anonymous lambda delegate and it gets a current reference to ctrl. That code may behave unexpectedly depending on situation and compile optimisation settings: whether or not the call is inlined or not.
Not to mention that there's architectural problem with the code: you have ControlOwner and a bunch of Child Controls. I take it you're adding child controls to ControlOwner at runtime, and then trying to react to their behavivour by subscribing ControlOwner to the childControl events. This is fine for events like _ButtonClicked etc. But not good for Dispose. Let the child control handle it's disposing on itself, the OwnerControl doesn't need to know about it. Not to mention that it may not exist at a time ChildControl[n].Dispose is called.
In short:
* it is better to leave dispose event on ChildControl alone and do all clean up in ChildControl.Dispose
* it is not necessary to unsubscribe from events. Event dispatcher will check if subscriber is alive.
public delegate void SecondChangedHandler(
object clock,
TimeInfoEventArgs timeInformation);
public event SecondChangedHandler SecondChanged;
I have written a clock based on this article.
Now if i remove the event keyword i get the same result, so what does event really do?
It's compiled differently. It makes it so someone can't do
mySecondChangedHandler.SecondChanged = SomeMethod(...); //overwrite
mySecondChangedHandler.SecondChanged(...); //invoke
but only
mySecondChangedHandler.SecondChanged += SomeMethod(...);
mySecondChangedHandler.SecondChanged -= SomeMethod(...);
The event keyword creates a private delegate field, and a pair of public event accessors called add_EventName and remove_EventName. (details)
This means that writing EventName inside the class returns the delegate instance, allowing you to call or inspect the event handlers.
Outside the class, EventName doesn't really exist; all you can do is write EventName += something and EventName -= something, and the compiler will convert it into calls to the accessors. (like a property)
For more details, see this series of blog posts.
The event keyword does two things
It supplied permissions. Only the class can raise the event, however any external method can invoke the raw delegate
It provides metadata which can be used for designers and the like
The event keywords means only methods on the instance that hosts the SecondChanged field can invoke it. External attempts will fail.
The event keyword creates a pair of accessors for a delegate. These are effectively two methods (add and remove) that are called when you subscribe or unsubscribe from the event.
In your case, you're creating a "field-like event". The compiler makes a delegate behind the scenes, and allows you to subscribe and unsubscribe from it's invocation list. This means that you have all of the functionality of a delegate, but you're restricting access so that that outside world can "handle" the event, but not raise the event (invoke the delegate).
You can, however, also explicitly create your own accessors for an event, and these can do other things (though that's not typically recommended unless there is a good reason to do so).
Quote from C# lang reference about keyword event,
Events are a special kind of multicast delegate that can only be invoked from within the class or struct where they are declared (the publisher class).
I have a Connection class which reads packets (commands) from a text stream and then distributes the commands to a set of handlers which process the commands as they see fit.
Eg.. Connection class reads in a command "HELLO" and then passes the command off to the handlers, where one or more handler may do something useful with the HELLO command.
Right now I use a delegate called HandleCommand which all command handlers must adhere to in order to receive the commands.
The question is, would it be more logical to use an event (eg.. CommandReceived) which the handlers could individually subscribe to? I'm having a hard time weighing up the pros and cons. it seems more wasteful to make it an event, because then an EventArgs class has to be generated for each command received.
In contrast, there is also a DisconnectCallback delegate which I strongly believe would be better as an event and will probably change.
Thank you
It seems your distributor now has to keep a list of handlers (class or delegates). That means you are duplicating the functionality of event.
The situation seems to call for events. It would decouple the components.
Concerning the 'wastefulness' of events and eventargs, see this question and stop worrying.
First - until you have evidence that it's a performance bottleneck, don't sacrifice clarity. The GC is fast and it's unlikely cleaning up a short-lived eventargs class will be the dominating performance factor here.
Anyway, If the consumers are only going to read and not modify the data, I'd make it an event. Otherwise you'd probably want to make an interface for a 'filter' that can read and modify, and pass the new value to the next one.
Events would be the most obvious approach as there are more than one command handlers.
I'm curious as to how command handlers "adhere" to a connection using delegates. You have to either simulate the event behavior by using a list of listeners or the command must actively call the handlers, what indeed compromises decoupling.
You are not required to use EventHandler or EventHandler<T> when creating an event, even though that is against Microsoft's recomendation. You can use your current delegate as the datatype for the event like so:
public event MyDelegateType EventName;
Edit:
If you are concerned about performance you can use an EventHandlerList class like so:
private EventHandlerList _events = new EventHandlerList();
private static object MyDelegateKey = new object()
public event MyDelegate EventName {
add {
_events.AddHandler(MyDelegateKey, value);
}
remove {
_events.RemoveHandler(MyDelegateKey, value);
}
}
I've just encountered a bug in the program I'm writing where an exception was thrown stating an "object reference must be set to an instance of an object". Upon investigation, I found that this exception was thrown when trying to fire an event BUT the event didn't have any delegate methods added to it.
I wanted to check that my understanding was correct that as a developer you shouldn't fire events without first checking that the event doesn't equal null? For example:
if (this.MyEventThatIWantToFire != null)
{
this.MyEventThatIWantToFire();
}
Thanks in advance for the advice/thoughts.
The pattern you've shown is broken in a multi-threaded environment. MyEventThatIWantToFire could become null after the test but before the invocation. Here's a safer approach:
EventHandler handler = MyEventThatIWantToFire;
if (handler != null)
{
handler(...);
}
Note that unless you use some sort of memory barrier, there's no guarantee you'll see the latest set of subscribers, even ignoring the obvious race condition.
But yes, unless you know that it will be non-null, you need to perform a check or use a helper method to do the check for you.
One way of making sure there's always a subscriber is to add a no-op subscriber yourself, e.g.
public event EventHandler MyEventThatIWantToFire = delegate {};
Of course, events don't have to be implemented with simple delegate fields. For example, you could have an event backed by a List<EventHandler> instead, using an empty list to start with. That would be quite unusual though.
An event itself is never null, because the event itself is just a pair of methods (add/remove). See my article about events and delegates for more details.
You shouldn't do it that way - if someone where to remove a listener between the if and the call to the event, you'd get an exception. It is good practise to use it with a local variable:
protected void RaiseEvent()
{
var handler = Event;
if(handler != null)
handler(this, EventArgs.Empty);
}
Of course, this has the disadvantage of maybe calling a listener that already was removed between the creation of the local variable and the call to the handler.
Yes, you should check it for null but the way you're doing it leads to a race condition. It's possible the event may end up being null anyway if someone unsubscribes the last delegate in between your "if" and your event raise. The accepted way to do this is like:
var temp = this.MyEventThatIWantToFire;
if (temp != null) {
this.temp(this, EventArgs.Empty);
}
or alternatively, ensure there's always at least one delegate in the invocation list by declaring your event like this:
public event EventHandler MyEventThatIWantToFire = delegate {};
Make sense?
Yes, your understanding is correct. It's up to you to check the delegate's value before calling it.
Most delegates - which events are - are "multi-cast" delegates. This means that a delegate can manage a list of one or more methods that it will call when activated.
When the delegate evaluates to a null value, there are no registered methods; therefore, there is nothing to call. If it evaluates to something other than a null value, there is at least one method registered. Calling the delegate is an instruction to call all methods it has registered. The methods are called in no guaranteed order.
Using the addition-assignment operator (+=) or addition operator (+) adds a method to the delegate's list of methods. Using the subtraction-assignment operator (-=) or subtraction operator (-) removes a method from the delegate's list of methods.
Also note that the called methods are executed from the caller's thread. This is important if you are using events to update your user interface controls. In this situation, use of your control's InvokeRequired property lets you handle cross-threading calls (using Invoke() or BeginInvoke()) gracefully.
Yes in C# if an event has no delegates, it will be null, so you must check
Yes, you must check whether event is not null. Mostly you encounter protected method that does the check and invokes event, or even constructs event args. Something like this:
public event EventHandler Foo;
protected void OnFoo() {
if (Foo == null)
return;
Foo(this, new EventArgs());
}
This approach also alows your derived classes to invoke (or prevent invoking) the event.
I've been looking into memory management a lot recently and have been looking at how events are managed, now, I'm seeing the explicit add/remove syntax for the event subscription.
I think it's pretty simple, add/remove just allows me to perform other logic when I subscribe and unsubscribe? Am I getting it, or is there more to it?
Also, while I'm here, any advice / best practices for cleaning up my event handles.
The add/remove properties are basically of the same logic of using set/get properties with other members.
It allows you to create some extra logic while registering for an event, and encapsulates the event itself.
A good example for WHY you'd want to do it, is to stop extra computation when it's not needed (no one is listening to the event).
For example, lets say the events are triggered by a timer, and we don't want the timer to work if no-one is registered to the event:
private System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
private EventHandler _explicitEvent;
public event EventHandler ExplicitEvent
{
add
{
if (_explicitEvent == null) timer.Start();
_explicitEvent += value;
}
remove
{
_explicitEvent -= value;
if (_explicitEvent == null) timer.Stop();
}
}
You'd probably want to lock the add/remove with an object (an afterthought)...
Yes, the add/remove syntax allows you to implement your own subscription logic. When you leave them out (the standard notation for an event) the compiler generates standard implementations. That is like the auto-properties.
In the following sample, there is no real difference between Event1 and Event2.
public class Foo
{
private EventHandler handler;
public event EventHandler Event1
{
add { handler += value; }
remove { handler -= value; }
}
public event EventHandler Event2;
}
But this is a separate topic from 'cleaning up' handlers. It is the subscribing class that should do the unsubscribe. The publishing class can not help with this very much.
Imagine a class that would 'clean' up the subscription list of its events. It can only sensibly do this when it is Disposed itself, and then it is unlikely to be productive as a Disposed class usually becomes collectable shortly after it is Disposed.
Add/remove syntax is commonly used to "forward" an event implementation to another class.
Cleaning up subscriptions (not "event handles") is best done by implementing IDisposable.
UPDATE: There is some variation on which object should implement IDisposable. The Rx team made the best decision from a design perspective: subscriptions themselves are IDisposable. Regular .NET events do not have an object that represents the subscription, so the choice is between the publisher (the class on which the event is defined) and the subscriber (usually the class that contains the member function being subscribed). While my design instincts prefer making the subscriber IDisposable, most real-world code makes the publisher IDisposable: it's an easier implementation, and there may be cases where there isn't an actual subscriber instance.
(That is, if the code actually cleans up event subscriptions at all. Most code does not.)