If I hook an event in a constructor, is there any possibility that the handler might be invoked by another thread before it's finished with the constructor?
e.g.:
private List<string> changes;
public MyClass(INotifyPropertyChanged observable) {
observable.PropertyChanged += this.Handler;
// Another thread changes a property at this point
this.changes = new List<string>();
}
private void Handler(object sender, PropertyChangedEventArgs e) {
this.changes.Add(e.PropertyName); // Breaks, because the list's not there yet
}
(Yes, I know it's trivial to avoid a problem in this example, I've got some more complex cases than this I'd like to make fully thread-safe)
I could probably just put a lock(obj) round both the event handler and the body of the constructor, but that feels clumsy and I suspect it's probably prone to deadlock somehow.
Is there a clean & reliable way of doing this?
ECMA-335 doesn't obligate a CLI to provide guarantee that the initialization changes which are made in a constructor should be visible before the constructor completion:
It is explicitly not a requirement that a conforming implementation of the CLI guarantee that all state updates performed within a constructor be uniformly visible before the constructor completes (see there, section I.12.6.8).
So the brief answer: avoid a subscription of an instance event handlers inside a constructor because it implies an exposure of the instance to external consumers with no guarantee that the instance is ready for consumption.
In details: typically semantic of a constructor implies only state initialization that is getting internal data of an instance into consistent state (when all its invariants are true and it's ready for consumption by other objects). The mechanism of events in C# in essence is adaptation of observer pattern which implies number of interactions between its participants and making of subscription is one of those interactions and as any other interaction with other object it should be avoided in a constructor when the instance isn't guaranteed to be initialized. You correctly noticed the possible scenario when it can become a problem but even with applying of protection mechanisms like reordering or synchronization, it cannot be guaranteed 100% safe, because it may not be provided by a CLI implementation or even if provided there is still possibility of scenarios when a constructor fails to complete for a reason not dependent on code inside the constructor, for example because of ThreadAbortException.
Of course there can be some relaxed requirements to design dictated by some well-known constraints (for example you can be 100% sure that your event publisher is implemented in the way which excludes critical scenarios) but in general case I'd suggest to make separation of construction and subscription scenarios when there is separate method, which is part of public contract and which is purposed only for making subscriptions.
How about using a thread-safe collection (like ConcurrentQueue) combined with the null conditional operator?
Thread-safe delegate invocation
Use the ?. operator to check if a delegate is non-null and invoke it in a thread-safe way (for example, when you raise an event).
class MyClass
{
private ConcurrentQueue<string> changes;
public MyClass(INotifyPropertyChanged observable)
{
observable.PropertyChanged += this.Handler;
// Another thread changes a property at this point
this.changes = new ConcurrentQueue<string>();
}
private void Handler(object sender, PropertyChangedEventArgs e)
{
this.changes?.Enqueue(e.PropertyName);
// Nothing breaks, changes during construction are simply not recorded
}
}
I read the excellent answer explaining how to use the Dispose pattern, and also why it works that way.
Proper use of the IDisposable interface
The post clearly states that you would want to use the Dispose pattern in two different scenarios:
get rid of unmanaged resources (because we have to)
get rid of managed resources (because we want to be helpful)
My question is:
When an object is subscribed to an external event for its entire lifetime, is it also common/good practice to unregister from that event in the Dispose method? Would you implement the IDisposable interface for that purpose?
Yes, you should.
This is the best way to indicate to consumers of your class that it has "resources" that must be released. (even though event subscriptions are technically not resources)
In many (most?) cases, an object will become eligible for garbage collection very soon after Dispose is called. For example, this will always be true for IDisposable objects instantiated with a using statement:
using(var myDisposableObject = ...)
{
...
} // myDisposableObject.Dispose() called here
// myDisposableObject is no longer reachable and hence eligible for garbage collection here
In this situation, I personally wouldn't clutter the code with removal of event subscriptions in the general case.
For example, an ASP.NET Page or UserControl is IDisposable, and often handles events from other controls on the web page. There is no need to remove these event subscriptions when the Page or UserControl is disposed, and in fact I've never seen an ASP.NET application where this is done.
UPDATE
Other answerers suggest you should always unsubscribe to events in the Dispose method of an IDisposable class.
I disagree with this in the general case, though there may be application-specific situations where it is appropriate.
The logical conclusion is that any class that subscribes to events should be IDisposable, so that it can unsubscribe deterministically - I see no logical reason why this recommendation should only apply to classes that happen to own unmanaged resources. I don't think this is a good general recommendation for the following reasons:
Making a class IDisposable just so it can unsubscribe from events adds complexity for users of the class.
Unsubscribing from events in the Dispose method requires the developer to keep a track of event subscriptions that need to be removed - somewhat fragile as it's easy to miss one (or for a maintenance developer to add one).
In situations where a class subscribes to events from a long-lived publisher, it is probably more appropriate to use a Weak Event Pattern to ensure that the subscriber's lifetime is not affected by the event subscription.
In many situations (e.g. an ASP.NET Page class subscribing to events from its child controls), the lifetime of publisher and subscriber are closely related, so there is no need to unsubscribe.
I prefer to have a two-pronged approach:
(1) An explicit method to UnregisterFromExternalEvents();
(2) A call in Dispose() to that method.
This way any code that controls instances of your class can either explicitly unregister, or trust on Dispose to properly dispose and take care of such matters.
Yes, it would be good practice to unregistered all external events, but though not extremely necessary, due to loose coupling nature of events.
It removes the event entry point reference of the subscriber object from the event generator and yes will be helpful.
For the part to unsubscribe in the dispose method is also fine. The thumb rule of Dispose method is - "Dispose method should unload resources in a way that if the dispose is called more than once it still works, i.e you should free resource in dispose one and only one time. (which would require checks before disposing resources)"
Yes, it is an extremely good idea. An event publisher holds a reference to the event subscriber which will prevent the subscriber from being garbage collected. (See Do event handlers stop garbage collection from occurring?)
In addition, if your event handlers use the resources you are releasing, then the event handlers (which will continue to be called by the event publisher) may generate exceptions after the resources have been released.
It is important, therefore, to unregister from any events before releasing your resources, especially if you are making use of async or multiple threads, as it is possible in some scenarios for an event to be raised between releasing a resource and unregistering from that event.
The following code demonstrates this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ReleaseEvents
{
class Program
{
public static event EventHandler SomethingHappened;
static void Main( string[] args )
{
using ( var l_dependent = new Dependent() )
{
SomethingHappened( null, EventArgs.Empty );
}
// Just to prove the point, garbage collection
// will not clean up the dependent object, even
// though it has been disposed.
GC.Collect();
try
{
// This call will cause the disposed object
// (which is still registered to the event)
// to throw an exception.
SomethingHappened( null, EventArgs.Empty );
}
catch ( InvalidOperationException e )
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine( e.ToString() );
}
Console.ReadKey( true );
}
}
class Dependent : IDisposable
{
private object _resource;
public Dependent()
{
Program.SomethingHappened += Program_SomethingHappened;
_resource = new object();
}
private void Program_SomethingHappened( object sender, EventArgs e )
{
if ( _resource == null )
throw new InvalidOperationException( "Resource cannot be null!" );
Console.WriteLine( "SomethingHappened processed successfully!" );
}
public void Dispose()
{
_resource = null;
}
}
}
The second time that the SomethingHappened event is raised, the Dependent class will throw an InvalidOperationException. You must unregister the event to prevent this from happening:
class Dependent : IDisposable
{
// ...
public void Dispose()
{
Program.SomethingHappened -= Program_SomethingHappened;
_resource = null;
}
}
I actually ran into this problem when I first tried to implement a MVVM architecture. When I was switching between ViewModels, I was simply releasing what I thought was my only reference (an ActiveViewModel property). I didn't realize that the events my ViewModel was subscribed to was keeping it in memory. As the application ran longer, it became slower and slower. Eventually I realized that the ViewModels I thought I had released were actually continuing to process events (expensively). I had to explicitly release the event handlers to fix this problem.
Thanks to this question I will write my classes as:
class Foo : IDisposable
{
public event EventHandler MyEvent;
/// <summary>
/// When disposing unsubscibe from all events
/// </summary>
public void Dispose()
{
if (MyEvent != null)
{
foreach (Delegate del in MyEvent.GetInvocationList())
MyEvent -= (del as EventHandler);
}
// do the same for any other events in the class
// ....
}
}
EDIT: After Joel Coehoorns excellent answer, I understand that I need to be more specific, so I modified my code to be closer to thing I'm trying to understand...
Events: As I understand, in the background the events are "collection" of EventHandlers aka Delegates which will be executed when event raised. So for me it means that if object Y has event E and object X subscribes to event Y.E, then Y will have reference to X, since Y must execute the method located in X, in that way, X can not be collected, and that thing i understand.
//Creates reference to this (b) in a.
a.EventHappened += new EventHandler(this.HandleEvent);
But it is not what Joel Coehoorn tells...
However, there is an issue with events such that sometimes people like to use IDisposable with types that have events. The problem is that when a type X subscribes to events in another type Y, X now has a reference to Y. This reference will prevent Y from being collected.
I not understand how X will reference the Y ???
I modified a bit my example to illustrate my case more closer:
class Service //Let's say it's windows service that must be 24/7 online
{
A _a;
void Start()
{
CustomNotificationSystem.OnEventRaised += new EventHandler(CustomNotificationSystemHandler)
_a = new A();
B b1 = new B(_a);
B b2 = new B(_a);
C c1 = new C(_a);
C c2 = new C(_a);
}
void CustomNotificationSystemHandler(args)
{
//_a.Dispose(); ADDED BY **EDIT 2***
a.Dispose();
_a = new A();
/*
b1,b2,c1,c2 will continue to exists as is, and I know they will now subscribed
to previous instance of _a, and it's OK by me, BUT in that example, now, nobody
references the previous instance of _a (b not holds reference to _a) and by my
theory, previous instance of _a, now may be collected...or I'm missing
something???
*/
}
}
class A : IDisposable
{
public event EventHandler EventHappened;
}
class B
{
public B(A a) //Class B does not stores reference to a internally.
{
a.EventHappened += new EventHandler(this.HandleEventB);
}
public void HandleEventB(object sender, EventArgs args)
{
}
}
class C
{
public C(A a) //Class B not stores reference to a internally.
{
a.EventHappened += new EventHandler(this.HandleEventC);
}
public void HandleEventC(object sender, EventArgs args)
{
}
}
EDIT 2: OK, now it's clear, when subscriber subscribes to a publishers events, it's NOT creates a reference to the publisher in subscriber. Only the reference from publisher to subscriber created (through EventHandler)...in this case when publisher collected by GC before the subscriber (subscribers lifetime is greater then publishers), there's no problem.
BUT...as I know, it's not guaranteed when GC will collect the publisher so in theory, even if subscribers lifetime is greater then publishers, it can happen that subscriber is legal for collection, but publisher is still not collected (I don't know if within closest GC cycle, GC will be smart enough to collect publisher first and then subscriber.
Anyway, in such case, since my subscriber do not have direct reference to publisher and can't unsubscribe the event, I would like to make publisher to implement IDisposable, in order to dispose it before delete all references to him (see in CustomNotificationSystemHandler in my example).
AND AGAIN What I should write in publishers dispose method in order to clear all references to subscribers? should it be EventHappened -= null; or EventHappened = null; or there's no way to do it in such way, and I need to make something like below ???
public event EventHandler EventHappened
{
add
{
eventTable["EventHappened"] = (EventHandler)eventTable["EventHappened"] + value;
}
remove
{
eventTable["EventHappened"] = (EventHandler)eventTable["EventHappened"] - value;
}
}
The life time of object B is longer that A, so A may be disposed earlier
It sounds like you are confusing "Disposal" with "Collection"? Disposing an object has nothing to do with memory or garbage collection. To make sure everything is clear, let's break up the two scenarios, and then I'll move on to events at the end:
Collection:
Nothing you do will ever allow A to be collected before it's parent B. As long as B is reachable, so is A. Even though A is private, it's still reachable from any code within B, and so as long as B is reachable, A is considered reachable. This means the garbage collector doesn't know for sure that you're done with it, and will never collect A until it is also safe to collect B. This is true even if you explicitly call GC.Collect() or similar. As long an object is reachable, it will not be collected.
Disposal:
I'm not even sure why you are implement IDisposable here (it has nothing to do with memory or garbage collection), but I'll give you the benefit of the doubt for the moment that we just don't see the unmanaged resource.
Nothing prevents you from Disposing A whenever you want. Just call a.Dispose(), and it's done. The only way the .Net framework will ever call Dispose() for you automatically is at the end of using block. Dispose() is not called during garbage collection, unless you do it as part of the object's finalizer (more on finalizers in a moment).
When implementing IDisposable, you are sending a message to programmers that this type should (maybe even "must") be disposed promptly. There are two correct patterns for any IDisposable object (with two variations on the pattern). The first pattern is to enclose the type itself in a using block. When this is not possible (for example: code such as yours where the type is a member of another type), the second pattern is that the parent type should also implement IDisposable so it can itself then be included in a using block, and it's Dispose() can call your type's Dispose(). The variation on these patterns is to use try/finally blocks instead of a using block, where you call Dispose() in the finally block.
Now on to finalizers. The only time you need to implement a finalizer is for an IDisposable type that originates an unmanaged resource. So, for example, if your type A above is just wrapping a class like SqlConnection, it does not need a finalizer because the finalizer in SqlConnection itself will take care of any needed cleanup. But, if your type A were implementing a connection to a whole new kind of database engine, you would want a finalizer to make sure your connections are closed when the object is collected. Your type B, however, would not need a finalizer, even though it manages/wraps your type A, because type A will take care of finalizing the connections.
Events:
Technically, events are still managed code and shouldn't need to be disposed. However, there is an issue with events such that sometimes people like to use IDisposable with types that have events. The problem is that when a type X subscribes to events in another type Y, Y now has a reference to X. This reference can prevent X from being collected. If you expected Y to have a longer lifetime then X, you can run into problems here, particularly if Y is very long-lived relative to many X's that come and go over time.
To get around this, sometimes programmers will have type Y implement IDisposable, and the purpose of the Dispose() method is to unsubscribe any events so that subscribing objects can also be collected. Technically, this is not the purpose of the Dispose() pattern, but it works well enough that I'm not going to argue about it. There are two things you need to know when using this pattern with events:
You do not need a finalizer if this is the only reason for implementing IDisposable
Instances of your type still need a using or try/finally block, or you haven't gained anything. Otherwise Dispose() will not be called and your objects still cannot be collected.
In this case, your type A is private to type B, and so only type B can subscribe to A's events. Since 'a' is a member of type B, neither is eligible for garbage collection until B is no longer reachable, at which point both will no longer be reachable and the event subscription reference won't count. That means a reference held on B by A's event would not prevent B from being collected. However, if you use the A type in other places, you may still want to have A implement IDisposable to make sure your events are unsubscribed. If you do that, make sure to follow the whole pattern, such that instances of A are enclosed in using or try/finally blocks.
I have added My comments in your sample code.
class A : IDisposable
{
public event EventHandler EventHappened
{
add
{
eventTable["EventHappened"] = (EventHandler)eventTable["EventHappened"] + value;
}
remove
{
eventTable["EventHappened"] = (EventHandler)eventTable["EventHappened"] - value;
}
}
public void Dispose()
{
//Amit: If you have only one event 'EventHappened',
//you can clear up the subscribers as follows
eventTable["EventHappened"] = null;
//Amit: EventHappened = null will not work here as it is
//just a syntactical sugar to clear the compiler generated backing delegate.
//Since you have added 'add' and 'remove' there is no compiler generated
//delegate to clear
//
//Above was just to explain the concept.
//If eventTable is a dictionary of EventHandlers
//You can simply call 'clear' on it.
//This will work even if there are more events like EventHappened
}
}
class B
{
public B(A a)
{
a.EventHappened += new EventHandler(this.HandleEventB);
//You are absolutely right here.
//class B does not store any reference to A
//Subscribing an event does not add any reference to publisher
//Here all you are doing is calling 'Add' method of 'EventHappened'
//passing it a delegate which holds a reference to B.
//Hence there is a path from A to B but not reverse.
}
public void HandleEventB(object sender, EventArgs args)
{
}
}
class C
{
public C(A a)
{
a.EventHappened += new EventHandler(this.HandleEventC);
}
public void HandleEventC(object sender, EventArgs args)
{
}
}
class Service
{
A _a;
void Start()
{
CustomNotificationSystem.OnEventRaised += new EventHandler(CustomNotificationSystemHandler)
_a = new A();
//Amit:You are right all these do not store any reference to _a
B b1 = new B(_a);
B b2 = new B(_a);
C c1 = new C(_a);
C c2 = new C(_a);
}
void CustomNotificationSystemHandler(args)
{
//Amit: You decide that _a has lived its life and must be disposed.
//Here I assume you want to dispose so that it stops firing its events
//More on this later
_a.Dispose();
//Amit: Now _a points to a brand new A and hence previous instance
//is eligible for collection since there are no active references to
//previous _a now
_a = new A();
}
}
b1,b2,c1,c2 will continue to exists as is, and I know they will now
subscribed to previous instance of _a, and it's OK by me, BUT in that
example, now, nobody references the previous instance of _a (b not
holds reference to _a) and by my theory, previous instance of _a, now
may be collected...or I'm missing something???
As explained through my comments in the above code, you are not missing anything here :)
BUT...as I know, it's not guaranteed when GC will collect the
publisher so in theory, even if subscribers lifetime is greater then
publishers, it can happen that subscriber is legal for collection, but
publisher is still not collected (I don't know if within closest GC
cycle, GC will be smart enough to collect publisher first and then
subscriber.
Since publisher references subscriber, it can never happen that the subscriber becomes eligible for collection before the publisher but reverse can be true. If publisher gets collected before subscriber then, as you said, there is no problem. If the subscriber belongs to a lower GC generation than publisher then since publisher holds a reference to subscriber, GC will treat the subscriber as reachable and will not collect it. If both belong to same generation, they will be collected together.
since my subscriber do not have direct reference to publisher and
can't unsubscribe the event, I would like to make publisher to
implement IDisposable
Contrary to what some have suggested, I would recommend implementing dispose if at any point you are deterministically sure that the object is no longer required. Simply updating an object reference may not always lead to an object stop publishing events.
Consider the following code:
class MainClass
{
public static Publisher Publisher;
static void Main()
{
Publisher = new Publisher();
Thread eventThread = new Thread(DoWork);
eventThread.Start();
Publisher.StartPublishing(); //Keep on firing events
}
static void DoWork()
{
var subscriber = new Subscriber();
subscriber = null;
//Subscriber is referenced by publisher's SomeEvent only
Thread.Sleep(200);
//We have waited enough, we don't require the Publisher now
Publisher = null;
GC.Collect();
//Even after GC.Collect, publisher is not collected even when we have set Publisher to null
//This is because 'StartPublishing' method is under execution at this point of time
//which means it is implicitly reachable from Main Thread's stack (through 'this' pointer)
//This also means that subscriber remain alive
//Even when we intended the Publisher to stop publishing, it will keep firing events due to somewhat 'hidden' reference to it from Main Thread!!!!
}
}
internal class Publisher
{
public void StartPublishing()
{
Thread.Sleep(100);
InvokeSomeEvent(null);
Thread.Sleep(100);
InvokeSomeEvent(null);
Thread.Sleep(100);
InvokeSomeEvent(null);
Thread.Sleep(100);
InvokeSomeEvent(null);
}
public event EventHandler SomeEvent;
public void InvokeSomeEvent(object e)
{
EventHandler handler = SomeEvent;
if (handler != null)
{
handler(this, null);
}
}
~Publisher()
{
Console.WriteLine("I am never Printed");
}
}
internal class Subscriber
{
public Subscriber()
{
if(MainClass.Publisher != null)
{
MainClass.Publisher.SomeEvent += PublisherSomeEvent;
}
}
void PublisherSomeEvent(object sender, EventArgs e)
{
if (MainClass.Publisher == null)
{
//How can null fire an event!!! Raise Exception
throw new Exception("Booooooooommmm");
//But notice 'sender' is not null
}
}
}
If you run the above code, more often than not you will receive the 'Booooooooommmm'. Hence idea is that event publisher must stop firing events when we are sure that its life is up.
This can be done through Dispose method.
There are two ways to achieve this:
Set a flag 'IsDisposed' and check it before firing any event.
Clear up the event subscribers list (as suggested in my comments in your code).
Benefit of 2 is that you release any reference to the subscribers, thereby enabling there collection (as I explained earlier even if the publisher is garbage but belongs to higher generation then it may still prolong collection of lower generation subscribers).
Though, admittedly, it will be quite rare that you experience the demonstrated behavior due to 'hidden' reachability of the publisher but as you can see benefits of 2 are clear and are valid for all event publishers especially long living ones (Singletons anybody!!!). This itself makes it worth to implement Dispose and go with 2.
Contrary to what some other answers claim, events whose publisher's GC lifetime may exceed a subscriber's useful lifetime should be regarded as unmanaged resources. The term "unmanaged" in the phrase "unmanaged resource" doesn't mean "completely outside the world of managed code", but rather relates to whether objects require cleanup beyond that provided by the managed garbage collector.
For example, a collection may expose a CollectionChanged event. If objects of some other type which subscribes to such an event are repeatedly created and abandoned, the collection may end up holding a delegate reference to each and every such object. If such creation and abandonment happens e.g. once per second (as might happen if the object in question were created in a routine that updates a UI window) the number of such references could grow by more than 86,000 for each day that the program was running. Not a big problem for a program which is never run for more than a few minutes, but an absolute killer for a program which could be run for weeks at a time.
It's really unfortunate that Microsoft didn't come up with a better event-cleanup pattern in vb.net or C#. There's seldom any reason why a class instance which subscribes to events shouldn't clean them up before it's abandoned, but Microsoft did nothing to facilitate such cleanup. In practice, one can get away with abandoning objects that are subscribed to events sufficiently often (because the event publisher will go out of scope around the same time as the subscriber) that the annoying level of effort necessary to ensure events get properly cleaned up doesn't seem worthwhile. Unfortunately, it's not always easy to predict all the cases where an event publisher might live longer than expected; if many classes leave events dangling, it's possible for huge amounts of memory to be uncollectable because one of the event subscriptions happens to belong to a long-lived object.
Addendum in response to edit
If X were to subscribe to an event from Y and then abandon all references to Y, and if Y became eligible for collection, X would not prevent Y from being collected. That would be a good thing. If X were to keep a strong reference to Y for the purpose of being able to dispose of it, such reference would prevent Y from being collected. That might arguably not be such a good thing. In some situations it would be better for X to keep a long WeakReference (one constructed with the second parameter set to true) to Y rather than a direct reference; if the target of the WeakReference is non-null when X is Disposed, it will have to unsubscribe from Y's event. If the target is null, it can't unsubscribe but it won't matter, because by then Y (and its reference to X) will have completely ceased to exist. Note that in the unlikely event that Y dies and is resurrected, X will still want to unsubscribe its event; using a long WeakReference will ensure that can still happen.
While some would argue that X shouldn't bother keeping a reference to Y, and Y should simply be written to use some sort of weak event dispatching, such behavior is not correct in the general case because there's no way for Y to tell whether X would do anything that other code might care about even if Y holds the only reference to X. It is entirely possible that X might hold a reference to some strongly-rooted object, and might do something to that other object within its event handler. The fact that Y holds the only reference to X should not imply that no other objects are "interested" in X. The only generally-correct solution is to have objects which are no longer interested in other objects' events notify the latter objects of that fact.
I would have my class B implements IDisposable as well and in it's dispose routine, I would first check whether A is not null and then dispose A. By using this approach you have to just make sure to dispose the last of your class and the internals will handle all other dispose.
MSDN Reference
"To prevent your event handler from being invoked when the event is raised, unsubscribe from the event. In order to prevent resource leaks, you should unsubscribe from events before you dispose of a subscriber object. Until you unsubscribe from an event, the multicast delegate that underlies the event in the publishing object has a reference to the delegate that encapsulates the subscriber's event handler. As long as the publishing object holds that reference, garbage collection will not delete your subscriber object."
"When all subscribers have unsubscribed from an event, the event instance in the publisher class is set to null."
You don't need to unhook event handlers when disposing of an object, although you may want to. By that I mean that the GC will clean up event handlers just fine without any intervention on your part, however depending on the scenario you may want to remove those event handlers before the GC does in order to prevent the handler being called when you weren't expecting it.
In your example I think you have your roles reversed - class A shouldn't really be unsubscribing event handlers added by others and has no real need to remove event handlers eiether, as it can instead just stop raising those events!
Suppose however that the situation is reversed
class A
{
public EventHandler EventHappened;
}
class B : IDisposable
{
A _a;
private bool disposed;
public B(A a)
{
_a = a;
a.EventHappened += this.HandleEvent;
}
public void Dispose(bool disposing)
{
// As an aside - if disposing is false then we are being called during
// finalization and so cannot safely reference _a as it may have already
// been GCd
// In this situation we dont to remove the handler anyway as its about
// to be cleaned up by the GC anyway
if (disposing)
{
// You may wish to unsubscribe from events here
_a.EventHappened -= this.HandleEvent;
disposed = true;
}
}
public void HandleEvent(object sender, EventArgs args)
{
if (disposed)
{
throw new ObjectDisposedException();
}
}
}
If its possible for A to continue raising events even after B has been disposed, and the event handler for B could do something that may cause either an exception or some other unexpected behaviour if B is disposed then its probably a good idea to unsubscribe from this event first.
The object A references B through EventHandler delegate(A has an instance of EventHandler wich references B). B don't have any reference to A. When A is set to null it will be collected and the memory will be freed.
So you don't need to clear anything in this case.
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.)
I'm working on a program that needs a Java object to have an event. I'm quite familiar with how this works in C#, having had enough experience to learn the pitfalls.
What are the pitfalls of working with events in Java? How are they different from events in C# 2.0?
Example: An object changed event to prompt a save from the owner object.
Note: Java 1.5
Related: C# event handling (compared to Java)
Java has no built-in concept of events, so you are best off using variations of The Observer Pattern.
In C#, you're supposed to do like this when you fire an event:
public event SomeDelegate MyEvent;
private void FireMyEvent(MyEventArgs args)
{
var deleg = MyEvent;
if (deleg != null) deleg(args);
}
... to protect yourself from concurrent modification (in case a thread removes an event listener between you checking the nullness of MyEvent and calling it). In Java, you'd use a CopyOnWriteArrayList instead to protect yourself from concurrent modification:
private final CopyOnWriteArrayList<MyEventListener> listeners =
new CopyOnWriteArrayList<MyEventListener>();
private void fireMyEvent(MyEventArgs args){
// Iteration is performed over a snapshot of the list, concurrent
// modifications from other threads are invisible to the iterator
// and will not cause ConcurrentModificationExceptions.
for (MyEventListener listener : listeners)
listener.eventOccurred(args);
}
As mentioned earlier, Java doesn't have delegates and events that C# has. But considering it's a "generalized" implementation of the Observer pattern (GoF) you can implement it on your own.
There are examples in the wikipedia page on how to implement the pattern with java.util.Observable and java.util.Observer. The general idea is to let classes that implement Observer to subscribe themselves to an Observable class.
I usually roll my own implementation since it is darn easy to do so, as you only need to make an interface declaring the methods that the "observable" class call to it's registered "observers". Here is a simple example of an observable class that can register SimpleObserver objects and perform some kind of event on them:
public class MyObservableClass {
List<SimpleObserver> observers = new ArrayList<SimpleObserver>();
/**
* Registers the observer
*/
public void addObserver(SimpleObserver observer) {
observers.add(observer);
}
/**
* Removes the registered observer (to be nice towards the
* garbage collector).
*/
public void removeObserver(SimpleObserver observer) {
observers.remove(observer);
}
/**
* Notifies the observers with the given data
*/
private void notifyObservers(String data) {
for(SimpleObserver o : observers) {
o.onEvent(data);
}
}
public void doSomething() {
// Do some stuff
String data = "Waffles and pwnies";
// Notify the observers that something happened.
notifyObservers(data)
}
}
…and here is the simple observer interface.
public interface SimpleObserver {
void onEvent(String data);
}
This may seem a bit complex, but the benefit is that the Observable class doesn't need to know what exact other objects are "listening" to it (which is why observers are sometimes called listeners). It provides a clean separation of concerns between them both. The Observers need to register themselves to an observable.
The only "gotcha" that I can think of is that of a memory leak that this pattern may cause even in a memory managed environment such as Java. This is because of the "reference islands" between Observers and Observables which will confuse the garbage collector and not attempt to remove the objects from memory. It is always a good idea to remove unused observers.
Java doesn't have a dedicated concept of Event. It's implemented through APIs along the lines of Observable + Observer. As far as I know, there is no dedicated lambda-functer API in the Java specification.
Events are strictly container specific in Java, and the standard library merely provides a generalized interface (which is typically extended for specific requirements).
The only 'gotcha' regarding events that can arguably be considered in context of Java (in general) is in Swing containers (Component) and event dispatching. The swing framework is single-threaded and you are expected to not use the event dispatch thread (i.e. the call back) to do computationally intensive/high-latency work in the event listener.