EventHandlers and C# Classes destructor/Dispose - c#

I'm a bit confused about C# Classes and their deconstructor.
I have to consume a few event handlers in a class instance I'm getting in the constructor:
public Foo(IFooHandler handler)
{
handler.Load += Load;
handler.Close += Close;
}
I need to unsubscribe to that event when the Foo class is destroyed. Do I implement IDisposable and unsubscribe in there, or in a deconstructor? I need to consume those events, I can't do it another way.
For one of the classes, I create an instance, check progress, and then the class instance goes out of scope. For another it stays in the MainForm until the form is closed. The first is what I'm worried about because it may still have a reference to that event handler and not properly go.
I don't want to leak memory. When and how should I unsubscribe?

Don't do it in the destructor, because it won't be called while the event handlers are attached : when you attach an instance method of Foo as a handler for an event of Bar, Bar will hold a reference to Foo, so Foo won't be garbage collected, and its destructor won't be called.
You should implement IDisposable, and dispose your object explicitly
public void Dispose()
{
if (handler != null)
{
handler.Load -= Load;
handler.Close -= Close;
}
}

If you ever face the problem of having class A be a long lived class and class(es) B be short lived ones that subscribe to events of class A then you probably would be interested in the Weak Event Pattern. It can be a problem that you do not discover is one until it is to late i.e. Princeton self driving car.

Related

Where to subscribe to events of the inner object?

I'm often encountering a situation where I must decide where to subscribe to events of the inner object?
For example, I have an object model looks like this:
class ClassA
{
public event EventHandler SomeEvent1;
public event EventHandler SomeEvent2;
public event EventHandler SomeEvent3;
public event EventHandler SomeEvent4;
}
class ClassB
{
private ClassA a;
public ClassA A
{
get
{
return this.a;
}
}
public ClassB()
{
this.a = new ClassA();
// here subscribe to some events (for example, SomeEvent1 and SomeEvent2)
// this.a.SomeEvent1 += OnSomeEvent1Raised;
// this.a.SomeEvent2 += OnSomeEvent2Raised;
}
}
class ClassC
{
public ClassB B { get; }
}
class ClassD
{
public ClassC C { get; }
public void SomeMethod()
{
// Here subscribe to another ones events of object C.B.A. For example:
C.B.A.SomeEvent3 += OnSomeEvent3Raised;
C.B.A.SomeEvent4 += OnSomeEvent4Raised;
}
private void OnSomeEvent4Raised(object sender, EventArgs e)
{
throw new NotImplementedException();
}
private void OnSomeEvent3Raised(object sender, EventArgs e)
{
throw new NotImplementedException();
}
}
I've tried to create something like a UML diagram:
Structure of existing code of my project has places where such object model exist (its has a places where subscribing to events implemented as in the example above - C.B.A.SomeEvent+= ).
I don't like it and want to change it.
I want to here from you the best practices about this situation.
Alternative approach is to duplicate all events of classA in the classB, classC, classD.
And then replace all subscriptions to events to ONE PLACE (I mean that in the classB we will subscribe/unsubscribe to all events of the object of ClassA. In the classC we will subscribe/unsubscribe to all events of the object of classB. And so on...) In this case all subscriptions and unsubscriptions will be in one place. Hope, you understand what I mean here.
Again, please rely on your knowledge and experience tell we how to resolve this situation.
UPDATE
Do you agree with me that subscriptions and unsubscriptions to events must be placed in ONE PLACE ?
Please, answer on this additional question too.
Thanks in advance.
You might be interested in an event aggregator.
What it basically does is decoupling the publishers from subscribers - it's kind of a event container. You could get the event aggregator through dependency injection (e.g. MEF) for each class you'd like to subscribe or publish from.
The way I personally use and like it the most, is the way Rob Eisenberg implemented the event aggregator in Caliburn Micro:
NuGet Gallery
Caliburn.Micro Event Aggregator Documentation
In your case object A, B and C would share the same instance of an event aggregator, which means as soon as events are published on this event aggregator, all these objects recognize it. Class A, B and C are able behave differently, caused by different handling of certain events.
EDIT
The use of an event aggregator is, that you subscribe to the aggregator itself with an instance of a class. The connection between publisher and subscriber class happens through relying to the same instance of the event aggregator. In case of Caliburn.Micro subscription to certain events happens through implementing a generic interface (IHandle<>).
For example: if you'd like to subscribe to MyCustomEvent you implement the IHandle<MyCustomEvent> interface in the class to be subscribed.
This requires an implementation of the void Handle(MyCustomEvent e) method from the IHandle<MyCustomEvent> interface for this type of event. This method gets called everytime a (new) MyCustomEvent is published on the shared event aggregator.
There is way too much public stuff in your example. Hope I'll make sense below:
ClassB contains an object of type ClassA, and handles some ClassA events
ClassC contains an object of type ClassB but events are ignored.
ClassD contains an object of type ClassC and handles events from the ClassA object inside the ClassB object contains in this ClassC objects
#2 and #3 are not good: ClassC should handle and implement the events, handling them and letting them "bubble up" (invoking their own, same, event) for ClassD to handle correctly.
Basically, all of them should handle all events, either reacting to them (as in ClassB to ClassA's events) or just propagating them.
Find nice solution here:
Csharp-NotificationCenter

What to do with delegate / event references in a class that implements IDisposable

I have been reading up on memory management and have come across a situation in a project where the book, nor Google has come up with an exact answer. I already know that delegates are manages objects and events are delegate instances. Having said that, delegate instances will be removed from memory once the application ends.
What I can't figure out is how to ensure that external code has freed up all event references by the time my class is disposed (either explicitly or by the GC). As an example, class A exposes an event and class B consumes it. Class B calls Dispose on class A without freeing up references to the delegates. Of course, we cannot throw an error from the Dispose method itself.
Following is a class with a delegate and another one that consumes it.
public class ClassB
{
private ClassA A { get; set; }
public ClassB()
{
this.A = new ClassA();
this.A.OnProcessed += new ClassA.DelegateProcessed(this.ClassA_Processed);
}
public void Process()
{
this.A.Process();
}
public void ClassA_Processed (ClassA sender, EventArgs e)
{
// Do something.
// Code written by another developer does not free up events before calling Dispose.
this.A.Dispose();
this.A = null;
}
}
public class ClassA: IDisposable
{
public delegate void DelegateProcessed (A sender, EventArgs e);
public event DelegateProcessed OnProcessed = null;
~ClassA() { this.Dispose(false); }
public void Dispose ()
{
this.Dispose(true);
System.GC.SuppressFinalize(this);
}
private void Dispose (bool disposing)
{
if (!this.Disposed)
{
if (disposing)
{
// Dispose managed resources here.
// Is it possible / advisable to dispose of delegates / events here?
// Will this adversely affect the consumer class?
this.OnProcessed -= new ClassA.DelegateProcessed(this.ClassA_Processed);
}
}
this.Disposed = true;
}
public void Process () { this.OnProcessed(this, new EventArgs()); }
public void ClassA_Processed (ClassA sender, EventArgs e) { }
}
The point is to ensure that ClassA qualifies for garbage collection no matter what the developer does with ClassB. The point is to minimize the amount of time ClassA spends in memory even if the consumer is careless.
UPDATE: It is clear from the answers that the events do not have to be explicitly removed from ClassA. As for the main question, weak references seem to be the way to go as answered below. The objective is to minimize the time ClassA stays in memory. Please let me know in case I have overlooked anythig.
IDisposable is used to deterministically release unmanaged resources.
There is no need to remove event handlers. For example, if you look at Windows Forms Form and UserControl classes, or ASP.NET Page and UserControl classes, all of which are IDisposable, you'll see extensive use of events, and no special handling during disposal.
Instead of the "classic" Event subscriptions, you should have a look at the Weak Event Patterns.
Event subscriptions may keep objects alive, even if these references are the only references left and the referenced object itself is already gone out of scope. In this case the referenced object will never be collected by the GarbageCollector and stays alive until the end of your application.
This causes serious memory leaks.
If you are using the Weak Events pattern you allow the GabageCollector to better determine if the object is still referenced or if the events are the only references. In this case the objects get collected and your resources get freed.
This section of the code:
private ClassA A { get; set; }
public ClassB()
{
this.A = new ClassA();
this.A.OnProcessed += new ClassA.DelegateProcessed(this.ClassA_Processed);
}
means you have to do nothing.
A B instance owns an A instance and the A has a ref (through the event) to B again.
When a B becomes unreachable then the A will also be collected (GC and circular references).
When the 'A' is Disposed (long) before the B then the 'A' will be collected too (directionality).
The IDispoable interface on A is pointless.
And concerning the implementation:
// class B
this.A.OnProcessed += new ClassA.DelegateProcessed(this.ClassA_Processed);
// in classA
this.OnProcessed -= new ClassA.DelegateProcessed(this.ClassA_Processed);
This won't work, 2 different this means they are 2 different methods.
A properly-written class should in its IDisposable.Dispose method unsubscribe from any events to which it has subscribed. If an object whose event was subscribed has a GC lifetime comparable to the useful lifetime of the object which subscribed (which is a very common case), it won't matter whether the subscription is cleaned up or left dangling. Unfortunately, if A is abandoned without unsubscribing itself from B's event, and something keeps a long-lived reference to B (deliberately or not), anything which keeps B alive will also keep alive A and anything to which A holds a direct or indirect reference (including objects which have active event subscriptions from A). It's very easy to end up with large forests of interconnected objects which will usually become eligible for garbage collection, but which will all have to be kept alive as long as any of them is needed.
It's too bad event subscription and unsubscription are so awkward. If there were an object type associated with events, an object which was going to subscribe to various events could use an "event manager" object to manage subscriptions (so one could say something like MyEventManager.Subscribe(SomeObject.SomeEvent, someProc) and then have MyEventManager.Dispose unsubscribe from all the events to which it had established subscriptions. Unfortunately, there's no decent way to have a method accept an event as a parameter, and thus no way to have a general purpose class to manage incoming subscriptions. The best one could do would probably be to have a CleanupManager class which would take a pair of delegates and be invoked something like `MyCleaner.Register(()=>{SomeObject.SomeEvent += someProc;}, ()=>{SomeObject.SomeEvent -= someProc();}) but that seems rather awkward.

C# Event handler subscription management

I have a class:
public abstract class BaseComponent { ... }
Within the constructor of that class we subscribe to an event handler e.g.
protected ObjectWithEventHandler eventObject { get; private set; }
public BaseComponent (ObjectWithEventHandler obj)
{
eventObject = obj;
eventObject.ChangedEvent += new EventHandler(eventObject_OnChangedEvent );
}
protected void eventObject_OnChangedEvent (object sender, EventArgs e) { ... }
Are there any hard and fast rules when it comes to EventHandler subscription & unsubscription?
Is it considered good practice to provide some clean-up code that unsubscribes the function from the EventHandler? I.e. implement IDisposable and unsubscribe from the EventHandler then?
Or am I worrying unduly?
If you have full control of the usage of BaseComponent and you know that EventObject's lifecycle is shorter or equal* with regard to BaseComponent's lifecycle, you can skip unsubscription code.
In all other cases I would include it. In this case implementing IDisposable is good style.
*) effectively, you are coupling eventObject's lifetime to BaseComponent, so it cannot live shorter, but it could still be equal when the two go out of scope together.
As long as object which exposes event (eventObject) is created inside a BaseComponent class - you can ignore explicit unsubscribing because it will be GCed automatically but explicit unsubscribe is a good practice anyway.
But if you're subscribing for event which exposed by an external object injected into BaseComponent you should implement IDisposable in the BaseComponent class and in the Dispose() method do cleanup.
You should provide some way to trigger unsubscription explicitly if there is any chance that the eventObject might live longer as instances of the classes derived from BaseComponent are supposed to live. Otherwise you would prevent garbage collection of your component, as eventObject holds a reference to it.
Implementing IDisposable() is a good way to accomplish this as long as you can assure that there is some code actually calling it. The finalizer would not call Dispose(), because the garbage collector would not try to clean up your component as long as it is subscribed to eventObject.ChangedEvent and eventObject is still alive.

Is it possible to register one event to another without helper method in C#?

I have two same events in different classes:
A.eventA
B.eventB
These two events: eventA and eventB are defined via the same delegate therefore the events have the same return value and parameters. Is it possible to fire A.eventA in the moment when B.eventB is fired?
I can write a method:
void return-value-of-delegate connect(parameters of delegate)
{
if (A.eventA != null)
{
A.eventA(parameters of delegate);
}
}
I was just wondering if I can shorten my code.
Thanks!
(Note: My code is a WPF project therefore WPF tag.)
EDIT: In class A is reference to the class B.
Whenever EventB fires, EventA also fires:
class A {
private B b;
public event EventHandler EventA {
add {
b.EventB += value;
}
remove {
b.EventB -= value;
}
}
public A() {
b = new B();
}
// ...
}
All the event listeners are registered in class B now.
You can not raise an event outside of the class. Only the class itself can raise it's own events. You can on the other hand, expose a public method accepting same parameters which internally raises the specified event.
Using Reflection is also not an option which only allows you to subscribe to and remove a subscription from an event of another class.
No, you can't, unless the code is in the class that declares the event. Events can only be fired from the declaring class. You probably have to consume an event with the arguments from both classes and in return fire the event, but you can't guarentee they will be fired at the same time, only about the same time, depending on the methods registered to each event, as they will be executed in the same thread.
The fact that the events are defined in different classes means that they are not the same event, even though they may have the same signature. You can't fire events from two separate classes at once.
Amongst other things, consider that an event is typically fired from an instance of a class. Which instance of B.eventB would you fire when A.eventA occurs?

Using WeakReference to resolve issue with .NET unregistered event handlers causing memory leaks

The problem: Registered event handlers create a reference from the event to the event handler's instance. If that instance fails to unregister the event handler (via Dispose, presumably), then the instance memory will not be freed by the garbage collector.
Example:
class Foo
{
public event Action AnEvent;
public void DoEvent()
{
if (AnEvent != null)
AnEvent();
}
}
class Bar
{
public Bar(Foo l)
{
l.AnEvent += l_AnEvent;
}
void l_AnEvent()
{
}
}
If I instantiate a Foo, and pass this to a new Bar constructor, then let go of the Bar object, it will not be freed by the garbage collector because of the AnEvent registration.
I consider this a memory leak, and seems just like my old C++ days. I can, of course, make Bar IDisposable, unregister the event in the Dispose() method, and make sure to call Dispose() on instances of it, but why should I have to do this?
I first question why events are implemented with strong references? Why not use weak references? An event is used to abstractly notify an object of changes in another object. It seems to me that if the event handler's instance is no longer in use (i.e., there are no non-event references to the object), then any events that it is registered with should automatically be unregistered. What am I missing?
I have looked at WeakEventManager. Wow, what a pain. Not only is it very difficult to use, but its documentation is inadequate (see http://msdn.microsoft.com/en-us/library/system.windows.weakeventmanager.aspx -- noticing the "Notes to Inheritors" section that has 6 vaguely described bullets).
I have seen other discussions in various places, but nothing I felt I could use. I propose a simpler solution based on WeakReference, as described here. My question is: Does this not meet the requirements with significantly less complexity?
To use the solution, the above code is modified as follows:
class Foo
{
public WeakReferenceEvent AnEvent = new WeakReferenceEvent();
internal void DoEvent()
{
AnEvent.Invoke();
}
}
class Bar
{
public Bar(Foo l)
{
l.AnEvent += l_AnEvent;
}
void l_AnEvent()
{
}
}
Notice two things:
1. The Foo class is modified in two ways: The event is replaced with an instance of WeakReferenceEvent, shown below; and the invocation of the event is changed.
2. The Bar class is UNCHANGED.
No need to subclass WeakEventManager, implement IWeakEventListener, etc.
OK, so on to the implementation of WeakReferenceEvent. This is shown here. Note that it uses the generic WeakReference<T> that I borrowed from here: http://damieng.com/blog/2006/08/01/implementingweakreferencet
class WeakReferenceEvent
{
public static WeakReferenceEvent operator +(WeakReferenceEvent wre, Action handler)
{
wre._delegates.Add(new WeakReference<Action>(handler));
return wre;
}
List<WeakReference<Action>> _delegates = new List<WeakReference<Action>>();
internal void Invoke()
{
List<WeakReference<Action>> toRemove = null;
foreach (var del in _delegates)
{
if (del.IsAlive)
del.Target();
else
{
if (toRemove == null)
toRemove = new List<WeakReference<Action>>();
toRemove.Add(del);
}
}
if (toRemove != null)
foreach (var del in toRemove)
_delegates.Remove(del);
}
}
It's functionality is trivial. I override operator + to get the += syntactic sugar matching events. This creates WeakReferences to the Action delegate. This allows the garbage collector to free the event target object (Bar in this example) when nobody else is holding on to it.
In the Invoke() method, simply run through the weak references and call their Target Action. If any dead (i.e., garbage collected) references are found, remove them from the list.
Of course, this only works with delegates of type Action. I tried making this generic, but ran into the missing where T : delegate in C#!
As an alternative, simply modify class WeakReferenceEvent to be a WeakReferenceEvent<T>, and replace the Action with Action<T>. Fix the compiler errors and you have a class that can be used like so:
class Foo
{
public WeakReferenceEvent<int> AnEvent = new WeakReferenceEvent<int>();
internal void DoEvent()
{
AnEvent.Invoke(5);
}
}
The full code with <T>, and the operator - (for removing events) is shown here:
class WeakReferenceEvent<T>
{
public static WeakReferenceEvent<T> operator +(WeakReferenceEvent<T> wre, Action<T> handler)
{
wre.Add(handler);
return wre;
}
private void Add(Action<T> handler)
{
foreach (var del in _delegates)
if (del.Target == handler)
return;
_delegates.Add(new WeakReference<Action<T>>(handler));
}
public static WeakReferenceEvent<T> operator -(WeakReferenceEvent<T> wre, Action<T> handler)
{
wre.Remove(handler);
return wre;
}
private void Remove(Action<T> handler)
{
foreach (var del in _delegates)
if (del.Target == handler)
{
_delegates.Remove(del);
return;
}
}
List<WeakReference<Action<T>>> _delegates = new List<WeakReference<Action<T>>>();
internal void Invoke(T arg)
{
List<WeakReference<Action<T>>> toRemove = null;
foreach (var del in _delegates)
{
if (del.IsAlive)
del.Target(arg);
else
{
if (toRemove == null)
toRemove = new List<WeakReference<Action<T>>>();
toRemove.Add(del);
}
}
if (toRemove != null)
foreach (var del in toRemove)
_delegates.Remove(del);
}
}
Hopefully this will help someone else when they run into the mystery event caused memory leak in a garbage collected world!
I found the answer to my question as to why this doesn't work. Yes, indeed, I am missing a minor detail: The call to += to register the event (l.AnEvent += l_AnEvent;) creates an implicit Action object. This object is normally held only by the event itself (and the stack of the calling function). Thus, when the call returns and the garbage collector runs, the implicitly created Action object is freed (only a weak reference is point to it now), and the event is unregistered.
A (painful) solution is to hold a reference to the Action object as follows:
class Bar
{
public Bar(Foo l)
{
_holdAnEvent = l_AnEvent;
l.AnEvent += _holdAnEvent;
}
Action<int> _holdAnEvent;
...
}
This works, but removes the simplicity of the solution.
Surely this would have a performance impact.
Its a bit like, why reference other assemblies in my solution when I can use reflection to dynamically read the assembly and make the relevant calls in it's types?
So in short ...
you use a strong reference for 2 reasons ...
1. Type safety (not really applicable here)
2. Performance
This goes back to a similar debate on generics over hashtables.
Last time I saw that argument put to the table however the poster was looking a the generated msil pre-jitted, maybe that can lend you some light on the problem?
One other thought though ...
What if you attached an event handler to say a com object event?
Technically that object is not managed so how does that know when it needs cleaning up, surely this boils down to how the framework handles scope right?
This post comes with the "it works in my head garantee", no responsibility is taken for how this post is portrayed :)
There are two patterns I know of for making weak event subscriptions: one is to have the event subscriber hold a strong reference to a delegate that points to him, while the publisher holds a weak reference to that delegate. This has the disadvantage of requiring all event firing to be done through a weak reference; it may gives the publisher no notice of whether any events have expired.
Another approach is to give everyone who's actually interested in an object a reference to a wrapper, which in turn holds a reference to the "guts"; the event handler only has a reference to the "guts", and the guts do not hold a strong reference to the wrapper. The wrapper also holds a reference to an object whose Finalize method will unsubscribe from the event (the simplest way to do this is have a simple class whose Finalize method calls an Action<Boolean> with a value of False, and whose Dispose method calls that delegate with a value of True and suppresses finalization).
This approach has the disadvantage of requiring all non-event operations on the main class to be done through a wrapper (an extra strong reference), but avoids having to use any WeakReferences for anything other than event subscription and unsubscription. Unfortunately, using this approach with standard events requires that (1) any class which publishes the events to which one subscribes must have a thread-safe (preferably lock-free as well) 'remove' handler that can be safely called from the Finalize thread, and (2) all objects which are directly or indirectly referenced by the object that's used for event unsubscription will be kept semi-alive until the GC pass after the finalizer has run. Use of a different event paradigm (e.g. subscribing to an event by calling a function which returns an IDisposable which one may use to unsubscribe) may avoid these limitations.
When you have an event handler, you have two objects:
The object of your class. (An instance of foo)
The object that represents your event handler. (For example, an instance of EventHandler or an instance of Action.)
The reason why you think you have a memory leak is that the EventHandler (or Action) object internally holds a reference to your Foo object. This will prevent your Foo object from being collected.
Now, why can't you write a WeakEventHandler? The answer is you can, but you basically have to make sure that:
Your delegate (instance of EventHandler or Action) never has a hard reference to your Foo object
Your WeakEventHandler holds a strong reference to your delegate, and a weak reference to your Foo object
You have provisions to eventually unregister your WeakEventHandler when the weak reference becomes invalid. This is because there's no way to know when an object is collected.
In practice, this isn't worth it. This is because you have tradeoffs:
Your event handler method will need to be static and take the object as an argument, this way it doesn't hold a strong reference to the object you want collected.
Your WeakEventHandler and Action objects are at a high risk for making it to Gen 1 or Gen 2. This will cause high load in the garbage collector.
WeakReferences hold a GC Handle. This might negatively impact performance.
Thus, making sure to correctly unregister your event handlers is a better solution. The syntax is simpler, memory use is better, and the application performs better.

Categories

Resources