What happens with event handlers when an object goes out of scope? - c#

Let's say we have the following setup:
public class ClassA
{
public event EventHandler SomeEvent;
}
public class ClassB : IDisposable
{
public void SomeMethod(ClassA value)
{
value.SomeEvent += (s, e) => { DoSomething(); };
}
void DoSomething() { }
void Dispose() { }
}
public static class Program
{
static void Main()
{
var a = new ClassA();
using (var b = new ClassB())
b.SomeMethod(a);
// POINT OF QUESTION!!
}
}
What happens when the event SomeEvent is raised after the "POINT OF QUESTION"?

It will call method of disposed object. That's why it is important to unsubscribe. It even can lead to memory leaks.

You should use the Dispose() method of ClassB to unsubscribe from the ClassA event. You run the risk of classes not being garbage collected which of course leads to potential memory leaks. You should always unsub from events.

Nothing you have above would unhook your event handler. Since both a and b go out of scope at the same time, you'd be safe. Since a and b can both be collected, then a will not keep b alive.
If you were to raise the ClassA.SomeEvent event after your using statement, then ClassB.DoSomething will be called even though b has been disposed. You would have to explicitly remove the event handler in this case.
If you were to retain a reference to a somewhere else, then b would be keep alive by a. Again, because the event handler has not been removed.

Nothing. Runtime doesn't know about Dispose method and call to this method inside using statement do nothing to memory management.
Garbage collection is all about memory management, but IDisposable (and Finalizer) is about resource management, so you still should think yourself and implement it manually (and propertly, for example unsubscribe in Dispose).

Related

Will several bindings of static/global Event handler to Events in a class, lead to a thread/memory leak?

I have a class with EventHandler bindings at the constructor, that will be instantiated thousand times within application lifecycle. The question is: Will this approach leads to memory/thread leaks?
I did this way (code below), because I need to be notified every time SomeMethod() runs, whatever instance run it. Foo class (the publisher) will be short-lived, however the handlers will live until the application closes.
I ask this because, when working with Windows Forms, each form can hold several event handlers/delegates and everything is fine because all those delegates are inside the form and will be disposed when the form closes. But how about static event handlers/delegates, that could be even on separate projects?
Will I need to write a destructor to detach those event handlers?
Should I go with Weak Event Pattern?
Restriction: I must do this with .NET 3.5. I know I could do this with TPL, setting a "Fire and Forget" Task.
Thank you in advance.
Code:
public class Foo
{
public event EventHandler SomeEvent;
public Foo()
{
SomeEvent += FooHandlers.Foo_SomeEvent1;
SomeEvent += FooHandlers.Foo_SomeEvent2;
}
public void RaiseEvents(EventHandler evt, EventArgs args)
{
var eventObj = evt;
var listeners = eventObj.GetInvocationList();
foreach (var listener in listeners)
{
var method = (EventHandler)listener;
ThreadPool.QueueUserWorkItem(callBack => method(this, args));
// Handlers will do a lot of things, so I don't want
// them blocking the Main thread
}
}
public void SomeMethod()
{
// do something here
RaiseEvents(SomeEvent, new EventArgs());
}
}
public static class FooHandlers
{
public static void Foo_SomeEvent1(object sender, EventArgs e)
{
//do something here
}
public static void Foo_SomeEvent2(object sender, EventArgs e)
{
//do something different here
}
}
Since your handlers are static methods the delegate you're adding to the event doesn't have an object instance, so there is no object instance being kept alive for the duration of the object with the event.
And even if you did use an object instance to attach the handler, it wouldn't be a problem, because the object with the event is short lived. The only time there is a problem is when the object with the event is long lived, and the object that has a handler to itself assigned is short lived, and consumes a lot of resources to keep alive.

Removing event-handlers in destructors in case both publisher and subscriber hold reference to each other

Lets say we have the following model:
public class Bar<T>:List<T>
{
public delegate void CollectionChangedDelegate();
public event CollectionChangedDelegate CollectionChanged;
}
public class Foo
{
Bar<object> MyCollection = new Bar<object>();
public Foo()
{
MyCollection.CollectionChanged += new Bar<object>.CollectionChangedDelegate(MyCollection_CollectionChanged);
}
public void MyCollection_CollectionChanged()
{
//Do Something
}
~Foo() //Would this work ?
{
MyCollection.CollectionChanged -= MyCollection_CollectionChanged;
}
}
Could the destructor of Class Foo be called in this case ?
It is pointless to do so. Let's assume that there is such a subscription. Now, for us to get to the ~Foo method we must be being collected, so we must be unreachable. Because of how events work, subscriptions make us reachable (the publisher has a reference to the subscriber) - so we can deduce that MyCollection is also unreachable. If it wasn't, we wouldn't be being collected.
And if MyCollection is unreachable, then either it has already been collected, or it is about to be collected. There is no need to unsubscribe.
Remove ~Foo: it is pointless here; actually, it is worse than pointless - in addition to serving no useful purpose, it forces the garbage collector to push this object through an extra step (the finalizer queue).
You might, however, want to add some kind of deterministic clean-up that does this; as Joroen notes, IDisposable may be of use - however, it is hard to say whether it is appropriate in the case without knowing more context.
first of all, I believe that you are trying to write ObservableCollection
You can find info here: http://msdn.microsoft.com/en-us/library/ms668604.aspx.
Now, if my object holds data-members that have a need to dispose, I would implement IDisposable and there I would dispose them, or at least remove the event subscription.
implment it like that:
class Foo:Idisposable
{
public void Dispose(bool b)
{
MyCollection.CollectionChanged -= MyCollection_CollectionChanged;
}
}

Garbage Collection for List Objects

I would like to ask what is the efficiency way the clean and dispose the object collected in the List (Of Object)?
Is that by calling the List.Clear() method will automatic clean all the object collected by it?
For Example consider the below example
public partial class Form1 : Form
{
FontCollection m_fontCollection;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
m_fontCollection = new FontCollection();
for (int i = 0; i < 5000; i++)
{
Font font = new Font("Arial", 23);
FontImpl impl = new FontImpl(font, Color.Black);
impl.AfterChange +=
new FontImpl.AfterChangeHandler(impl_AfterChange);
m_fontCollection.Add(impl);
}
m_fontCollection.Dispose();
MessageBox.Show("TakeSnap");
}
void impl_AfterChange()
{
throw new NotImplementedException();
}
}
public class FontCollection : IEnumerable, IDisposable
{
IList<FontImpl> m_Implementation = new List<FontImpl>();
internal void Add(FontImpl impl)
{
this.m_Implementation.Add(impl);
}
public IEnumerator GetEnumerator()
{
return this.m_Implementation.GetEnumerator();
}
public void Dispose()
{
m_Implementation.Clear();
m_Implementation = null;
}
}
public class FontImpl
{
private Font m_Font;
private Color m_color;
public FontImpl(Font newFont, Color newColcor)
{
m_Font = newFont;
m_color = newColcor;
}
public event AfterChangeHandler AfterChange;
public delegate void AfterChangeHandler();
}
When i run the above application ANTS memory profiler i could see the memory leaks Font and FontFamily (I could not able to upload the screen) and how to remove these leaks
In general, you shouldn't need to worry about garbage collection, and when it occurs. An object is eligible for GC when there are zero references to it.
The thing you should pay attention to, however, are IDisposable objects. When you are finished with an IDisposable object, you really need to be calling Dispose() on it. If the object lives within the local scope of a functinon, then a using block makes this easy:
using (var resource = new SomeIDisposable()) {
// use resource
// resource.Dispose() is automatically called, *even if* an exception
// is thrown.
}
You can cause memory leaks by ending up with "dangling references" to objects, which prevent them from being garbage collected. Most often the cause of this is with event handlers. When you subscribe to an event exposed by object A, with an event handler on object B, A gets a reference to B:
class B {
void hook_up_to(A a) {
a.SomeEvent += Handler; // `a` gets a reference to `this`
}
void Handler(object sender, EventArgs e) {
}
}
class Program {
private A _a = new A();
static void SomeMethod() {
var b = new B();
b.hook_up_to(_a); // _a now has a reference to b
// b goes out of scope.
}
}
Normally, when b goes out of scope, the object it references would be eligible for garbage collection. In this case though, b hooked up to an event published by member variable _a, which caused _a to gain a reference to b. Now there is one outstanding reference to b, which is impossible1 to clear, and b is ineligible for GC. This is a memory leak.
1 The only way reference to b in this case is this pointer if/when the event handler is fired.
You don't need to implement IDisposable on your class. In general the only time your class needs to implement IDisposable is when it contains other classes that need to be disposed of (things like database and network connections, and unmanaged objects).
In your example, you might want to consider making m_fontCollection a local variable within button1_Click, since you're creating and disposing of it entirely within that method. If you make it local, then it will be garbage-collected once button1_Click exits ... provided there are no remaining references to it (which indeed there are not in this case).
Clear just removes everything from the list. In your case you have a list of IDisposable objects and you need to call Dispose on all the items in the list. Calling Clear does not do that.
Your FontImpl should implement IDisposable since it manages an IDisposable object:
public void Dispose() {
if (m_Font != null) {
m_Font.Dispose();
m_Font = null;
}
}
And your FontCollection Dispose should look like this:
public void Dispose()
{
foreach(FontImpl font in m_Implementation) {
font.Dispose();
}
m_Implementation.Clear();
m_Implementation = null;
}
In the case of the code you have shown you have Font objects which implement IDisposable and thus should be disposed. Those objects are being managed by your FontImpl class and so FontImpl should implement IDisposable. Your FontCollection class contains a list of FontImpl objects which should now be disposable and so FontCollection needs to implement IDisposable.
You should read up on the IDisposable pattern (this SO answer gives some great information - https://stackoverflow.com/a/538238/416574).
That being said, from the code snippet you provided it does not appear that you gain anything from your FontCollection other than a class to wrap a list. Unless there are other things you are going to do with that class I would just have a list as a member variable. That way in the Dispose method of your form you can walk your list and dispose the FontImpl objects. If you want to protect from double disposing, then just empty the list after disposing everything.

Object doesn't get garbage collected

I think this is a C# beginner question, but I can't seem to find a correct solution.
I have a ClassOne object, which defines an event.
I create a ClassTwo object, which is considered as a black box, which means I don't know whether it will register to any event or not. ClassTwo constructor registers to the event of ClassOne.
The problem comes, when ClassTwo object goes out of scope. The garbage collector never deletes this object, because it never deregistered the event.
So I have two questions:
Is there a way for ClassTwo object to know, when it goes out of scope? For an old C++ programmer this would be in the destructor, but with C# this doesn't work.
Is there a debug tool which helps me to find such objects?
Here is a sample code to reproduce the issue:
public partial class MainWindow : Window
{
static public ClassOne classOne = new ClassOne();
public MainWindow()
{
InitializeComponent();
ClassTwo classtwo = new ClassTwo();
}
private void buttonTest_Click(object sender, RoutedEventArgs e)
{
GC.Collect();
}
}
public class ClassOne
{
public ClassOne()
{
Trace.WriteLine(this + " constructor");
}
~ClassOne()
{
Trace.WriteLine(this + " destructor");
}
public delegate void UpdateFunc(object sender, EventArgs args);
public event UpdateFunc OnUpdate;
}
public class ClassTwo
{
public ClassTwo()
{
Trace.WriteLine(this + " constructor");
MainWindow.classOne.OnUpdate += new ClassOne.UpdateFunc(classOne_OnUpdate);
}
void classOne_OnUpdate(object sender, EventArgs args)
{
throw new NotImplementedException();
}
~ClassTwo()
{
Trace.WriteLine(this + " destructor");
}
}
I would implement IDisposable on an object like this and unregister from the event in the Dispose method.
You would use your object like this:
using(var two = new ClassTwo(classOne))
{
// Do something with two
}
// object can now be garbage collected.
If the caller fails to call Dispose, you are out of luck.
Not unless it implements IDisposable and the caller cooperates by calling Dispose correctly.
(Of course, why wouldn't the caller cooperate?)
Not that I've of. :( I think your best bet is to implement IDisposable and unregister on Dispose.
As other people have mentioned, the Dispose pattern is the way to address this issue. If the ClassTwo object lives for a short time, you can use the C# using statement to ensure Dispose is called after you are finished using the object:
using (var foo = new ClassTwo())
{
foo.Bar();
}
In order to find the root cause of such issues, you need to use a memory profiler. dotTrace has already been mentioned, and another good one is the SciTech Memory Profiler. What you need to find is the Root Path to the object that you think should be garbage collected, but isn't. The root paths are the reason why the object is not being collected - because through transitive references, an object that's guaranteed to be alive (a GC Root) is referencing your object that you want to be dead.
These memory profilers are very helpful in identifying which GC roots are causing you trouble, and what the reference paths are from the root to your object. Somewhere along that root path will be a reference that is out of place, and is the cause of the problem.
In your code, the cause of the ClassTwo object not being collected could be either the fact that MainWindow has a static reference to the ClassOne object, or that the event handler from ClassOne to ClassTwo has not been unhooked. Static references are one example of GC Roots - so everything classOne references will be alive until that static reference in MainWindow is changed.
Whether the static or the event handler is the problem depends on the scenario of your application - should the ClassOne object also be collected - is it wrong to have a static reference to it? Or is the static reference desired behaviour - is classOne a long lived object and classTwo a short lived one, in which case, classTwo should be Disposed when its life is over, and the Dispose should unhook the event handler.
This is a good article to learn about the .Net GC, written by Jeffrey Richter: http://msdn.microsoft.com/en-us/magazine/bb985010.aspx. It's a bit old now, there have been new additions to the GC over recent years, but it's a great place to start.

What happens to the event of method scoped variable?

Consider the following code:
public class Bar {
Foo foo;
void Go() {
foo = new Foo();
foo.Send(...);
foo.Dispose();
foo = null;
}
}
public class Foo : IDisposable {
public void Send(byte[] bytes) {
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
args.SetBuffer(bytes, 0, bytes.Length);
args.UserToken = socket;
args.RemoteEndPoint = endPoint;
args.Completed += new EventHandler<SocketAsyncEventArgs>(OnSendCompleted);
socket.SendAsync(args);
}
private void OnSendCompleted(object sender, SocketAsyncEventArgs e) {
Debug.WriteLine("great");
}
public void Dispose() {
//
}
}
So class Bar runs the Init method which instantiates the Foo class and fires off the Send method, then destroys the Foo instance. The Send method meanwhile instantiates a method level SocketAsyncEventArgs, sets up a Completed event and then fires off the SendAsync method.
Assuming that the SendAsync completes after the Foo instance has been set to null, what happens to the event handler? Does it still fire? If I don't want it to fire, how do I properly clean up the Foo class, knowing that a method level variable spawned off an event.
Yes, it will still fire. Setting a variable to null doesn't trigger garbage collection or anything like that. It just sets the variable to null. (It's important to differentiate between a variable and an instance. There's no such concept as "setting an instance to null". If I write my home address down on a piece of paper, then rub it out again, that doesn't destroy my house.)
It sounds like you may want your Dispose method to "remember" that the object has been cleaned up, and then if OnSendCompleted is called after disposal, just ignore it. Alternatively, keep track of any "requests in flight" and cancel them in in Dispose... noting that some requests might complete while you're cancelling the whole lot.
Another point to note: instead of explicitly calling Dispose(), you should almost always use a using statement, which will make sure that Dispose() is called however the using statement ends (e.g. with an exception).
What about trying to unhook the event by using -= in your OnSendCompleted method ?
e.Completed -= new EventHandler<SocketAsyncEventArgs>(OnSendCompleted);

Categories