Registering for an event on FileSystemWatcher causes the registering class to stay in memory even after eliminating all (my) references to the FileSystemWatcher and letting the GC and finalizers run. I've constructed an example below showing how an object using FileSystemWatcher stays in memory while another set of objects (of type A and B) which use similar events/eventhandlers do not stay in memory.
Example
class Program
{
class UsesFileWatcher
{
public FileSystemWatcher fw;
public UsesFileWatcher()
{
fw = new FileSystemWatcher(#"C:\", "*.txt");
fw.Changed += eventHandler;
fw.EnableRaisingEvents = true;
}
void eventHandler(object sender, FileSystemEventArgs e)
{
}
}
// For Comparison, I have classes A and B which use similar events and event handlers
class A
{
public event EventHandler AEvent;
}
class B
{
public A a;
public B()
{
a = new A();
a.AEvent += eventHandler;
}
void eventHandler(object sender, EventArgs e)
{
}
}
static void Main(string[] args)
{
var weakRefToB = WeakReferenceToB();
var weakRefToUsesFileWatcher = WeakReferenceToUsesFileWatcher();
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("B Alive = {0}", weakRefToB.IsAlive);
Console.WriteLine("UsesFileWatcher Alive = {0}", weakRefToUsesFileWatcher.IsAlive);
Console.ReadKey();
}
static WeakReference WeakReferenceToB()
{
return new WeakReference(new B());
}
static WeakReference WeakReferenceToUsesFileWatcher()
{
return new WeakReference(new UsesFileWatcher());
}
}
Notes:
I understand that FileSystemWatcher implements IDisposable and that I should be calling Dispose() when I'm done with it. But my understanding is that if I miss the call to Dispose() that it just means that the work it needed to do would be done later during the finalizer.
There is a known FileSystemWatcher memory leak documented here. But the description sounds different than what I'm describing.
I used Red Gate's ANTS Memory Profiler to show what is keeping it alive:
Question:
Is this a bug in FileSystemWatcher or are my expectations incorrect somehow?
Of course it's not a bug. You can see right in the profiler that the object is being referenced. There's a system type that is rooted that has a callback tot he FSW, making it accessible from a rooted object.
It will remove those callbacks when it is disposed of, enabling it to be collected, so you'll need to dispose it if you want it to be eligible for collection.
Related
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.
This may seem like a silly question, but I just want to make sure I have it right. My main form is not visible most of the time. To open it I have a NotifyIcon. One of the menu options is Exit Application. I also have a few static global variables that need to be disposed of before the application closes. so in program.cs i have this.
[STAThread]
static void Main()
{
InitializeApplication();
InitializeMainForm();
Application.Run(main);
}
private static void InitializeApplication()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ApplicationExit += Application_ApplicationExit;
}
private static void InitializeMainForm()
{
main = new AssignButtonForm();
main.FormClosing += main_FormClosing;
Globals.StartNotify();
}
static void main_FormClosing(object sender, FormClosingEventArgs e)
{
var dlg = MessageBox.Show("Turn off Application?", "Exit?", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
if (dlg == DialogResult.OK)
{
Globals.notifyIcon1.Dispose();
Application.Exit();
}
else
{
e.Cancel = true;
}
}
So what i'm hoping is that this is the correct way to call that.
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Hide();
Application.OpenForms[0].Close();
}
is that correct? or is there a better way?
EDIT
ok so one of my classes that has its own Dispose method
public class KeymonNotifyIcon : IDisposable
{
public KeymonNotifyIcon()
{
InitializeComponent();
keymonMenuStrip.SetupKeysSelected += OnSetupKeysSelected;
}
~KeymonNotifyIcon()
{
Dispose();
}
public void Dispose()
{
if (notifyIcon1 != null)
notifyIcon1.Dispose();
if (keymonMenuStrip != null)
keymonMenuStrip.Dispose();
}
}
The global class
public static class Globals
{
public static TraceSource trace = new TraceSource("Keymon");
public static KeymonNotifyIcon notifyIcon1;
public static void StartNotify()
{
notifyIcon1 = new KeymonNotifyIcon();
}
}
Actually, I am fairly certain that Application.Exit will call all of your Dispose methods for you (as long as you have implemented IDisposable
See this question, which references this question
If your program just shuts down, objects that have not been garbage collected will have their finalizers run. It is the recommended pattern that objects implementing IDisposable have a finalizer to ensure that IDisposable is run. To the best of my knowledge, .NET BCL classes always follow that pattern. However, your own or third-party/open source components might not follow that pattern.
Note: The linked pattern on MSDN does not call GC.SuppressFinalize. Check out how to use it to reduce the GC overhead.
Implementing IDisposable alone isn't sufficient to ensure that the object is properly disposed.
If you have statically referenced objects that implement IDisposable, it is a more solid solution to explicitly call IDisposable.Dispose() on them from an application shut down event.
EDIT
Your Dispose implementation will cause Dispose() to be called twice on the owned objects because:
if (notifyIcon1 != null)
notifyIcon1.Dispose();
does not set notifyIcon1 to null, and the finalizer unconditionally calls Dispose() again.
Additionally, you will always cause the finalizer to run (which makes GC more expensive for that class) because you do not call GC.SuppressFinalize() in Dispose().
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.
I have problem with destructor after going out of scope(it is calling but after some time and need to make an action on form, for example change radio button), maybe there's mistake in my code. Take a look:
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
EventLogger.Print += delegate(string output)
{ if (!textBox1.IsDisposed) this.Invoke(new MethodInvoker(() => textBox1.AppendText(output + Environment.NewLine)), null); };
}
private void button1_Click(object sender, EventArgs e)
{
TestClass test = new TestClass();
}
}
public static class EventLogger
{
public delegate void EventHandler(string output);
public static event EventHandler Print;
public static void AddLog(String TextEvent)
{
Print(TextEvent);
}
}
public class TestClass
{
public TestClass()
{
EventLogger.AddLog("TestClass()");
}
~TestClass()
{
EventLogger.AddLog("~TestClass()");
}
}
}
Right, because this isn't C++. The finalizer (not destructor as in C++) is not guaranteed to be called immediately after an object has left its declaring scope, it is called when the GC decides to swoop in and clean up after you.
May I ask why you are using a finalizer to begin with? Are you maintaining references to unmanaged resources which need to be deallocated as deterministically as possible (if so, read up on the IDisposable interface)? The use cases for C# finalizers are few and far between, it's not common to implement them.
C# is not C++. Destructors don't run synchronously.
There is no bugs in your code as is, but it looks like you may need to implement "IDisposable pattern" for your class to provide a way for caller to guaranty that some destruction of your object is executed synchronously.
For those of us who are more comfortable with the C++ pattern it's useful to check out the docs for the IDisposable interface:
http://msdn.microsoft.com/en-us/library/system.idisposable.aspx
Unfortunately I've just tried it and it's not working as I'd like. I used an automatic object to save the current state of the GUI cursor, switch to the wait cursor and restore the original cursor as the object goes out of scope. The IDisposable interface does result in the cursor being restored but not immediately - so the Wait Cursor is showing for too long. Too bad because this is a very useful pattern.
Update: The C# try/finally pattern is comfortable enough after a while:
public void do_something_time_consuming()
{
ShowBusyCursor cursor = new ShowBusyCursor();
try
{
...
return;
}
finally
{
cursor.done();
}
}
The finalizer is not designed to be called immediately after going out of scope. It is called when the object is garbage-collected, which be may anywhere from milliseconds to days after going out of scope.
The finalizer is NOT meant for this kind of code. It is only for resource cleanup.
You can't force it to do something immediately after going out of scope, but you can tell it to immediately before going out of scope, with a Close() or similar method to signal that the object is done being used.
For example:
private void button1_Click(object sender, EventArgs e)
{
TestClass test = new TestClass();
// do stuff
test.Close();
}
Note: You could implement IDisposable, as has been suggested, but this use doesn't exactly fit the intended use of IDisposable, so although it would work, it's a bit hackish.
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).