Do I have to get rid of ALL of these undisposed instances for my app not to leak memory...is this typical of .Net apps? In your docs you mentioned that some classes do not need to be disposed. Where is this information..I dont want to spend hours trying to trace an undisposed instances that do not need to be disposed.
I also found that the instances of the Process class still appear as undisposed event though I have called dispose on them (MS mention something about not needing this in the compact framework).
I thought the .Net framework sorted most things out but having used the profiler I am not so sure now.
If possible, you should try to make sure that all instances are correctly disposed. However, it's pretty common that the .NET Framework itself causes undisposed instances and there's nothing you can do about it.
The SafePEFileHandle is a wrapper class for an unmanaged resource. Failing to dispose instances of this class will keep the resource alive for an unneccessarily long time, but the finalizer will make sure that the resource is eventually released.
It's a bit more strange that you have undisposed instances of WindowsFormsSynchronizationContext. Only one instance of this class is supposed to be created for each UI thread. Disposing a WindowsFormsSynchronizationContext instance will also dispose the MarshallingControl, which might cause undesired side effects. Do you have more than one UI thread in your application? What does the allocation call stack look like for the undisposed WindowsFormsSynchronizationContext instances?
.NET Memory Profiler 3.5 will provide additional information about what the dispose methods performs for each class, giving you a better understanding of how important it is to dispose its instances.
SciTech Software AB
If you create a WinForms project with a single blank form and run the profiler, then look at the Undiposed instances you get quite a few including the WindowsFormsSynchronizationContext!
In my app I have a dynamically created control that displays photographs of users and also displays a couple of fixed icons in PictureBoxes. I have been using the profiler to locate undiposed bitmap instances and I have found the following:
If you have a PictureBox (which already contains an image) before you set a new image you must call Dispose()... this reduces the number of undiposed instances listed in the profiler.
I was still getting some undiposed bitmaps (in PictureBoxes) that have been loaded directly from the parent Control's resources. After some testing I have found the following:
1. Create a Winforms app with a Form and button.
2. Add a second Form with a PictureBox containing a Bitmap.
3. Set the button of the main Form to open the second Form
4. Run the app via the profiler and click the button to open the second Form about 10 times.
5. Look at the undisposed Bitmap instances which creep up each time you open the second form!
I think this is the cause:
1. The Bitmap is loaded directly from the resource so there is no variable (in the app code) holding a reference.
2. The GC collects the short lived image reference
3. The bitmap instance then becomes undisposed.
To fix this is I added a class level field to hold a reference to the image.
In this initialize event I added this.img = PictureBox1.Image;
In the Dispose override:
if (this.img != null)
Run the app again through the profiler and you dont get any undisposed instances!!
The problem seems to be with images loaded from the resources. I think the same may be true for Fonts.
Using the profiler an a short time has taught me so much about the .Net framework but also makes me question what I thought I knew!
I suppose the key to using the profile is knowing what is a problems and what is not.
Hope this makes some sort of sense!!
Regarding the undisposed Bitmaps. Unfortunately it is not possible to avoid undisposed resources that are retrieved from the ResourceManager. From the MSDN documentation:
Since it's not possible to know whether you will receive a cached instance or a new instance, you cannot dispose it yourself. You can mitigate the problem by only retrieving the resource once from the ResourceManager, but it will make things less convenient (e.g. it will prevent you from assigning the Bitmap in the Form designer).Performance Considerations
If you call the GetObject method multiple times with the same name parameter, do not depend on the return value being a reference to the same object. This is because the GetObject method can return a reference to an existing resource object in a cache, or can reload the resource and return a reference to a new resource object.
SciTech Software AB
One last question regarding undisposed instances. I have also been getting a large number of undisposed Fonts. Using the pofiler I have found out why.
In my app I have used the Tahoma Font for all forms and controls. As this is not the default font the designer adds a line in the designer created code to create instances of the fonts...it is these instances that become undisposed instances. If you use the default font then the number of undiposed instances is reduced considerably. I assume that the runtime will call the finalize method on these instances. Am I correct in assuming that I can ignore these?
Is there a way to tell if the finalizer has been called on these instances.
I would like to add that the Memory Profiler is an excellent product and I am wondering how I ever managed without it
If a finalizable instance is counted as undisposed, then the finalizer has been run (or is at least running).
SciTech Software AB
So, what 'Andreas Suurkuusk' mentioned above to ignore the is NOT correct.
This problem is very similar to http://forum.memprofiler.com/viewtopic. ... 337&p=6645
The industry in which I work, there the deployed applications are rarely re-started. So, even 1 handle leak per day also can't be ignored. Recently, we were noticing handle leaks from our applications. During investigation we found very interesting items:
1) If you are creating a new thread and then create any WinForms or WPF based control/UI on it, there will be handle leak.
2) This is mainly caused because of the ThreadContext that is created due to
=> In WinForm => WinFormSynchronizationContext
=> In WPF => Dispatcher is created automatically, which internally forces the ThreadContext to be created.
=> WPF: Simple fix is to call Dispatcher.InvokeShutdown() or follow similar approach as for WinForms mentioned below (keeping the dispatcher object)
Solution 1) Run the Message pump and add the Exit message in the message pump. OR
Solution 2) Create a single dedicated thread and use it if you want to create any UI object. To do this, on the new thread you must first create a WinForm based control which will force the creation of SynchronizationContext. Then store reference of SynchronizationContext.Current (say uiContext) in some static variable, then call Application.Run() to keep the thread running. Now, you can use uiContex.Send() to execute the code on the UI thread.
However, I didn't suggest that you should ignore a leaked handle. I said that you could ignore undisposed instances of the System.Drawing.Font class. An undisposed instance is not a leaked instance. It becomes marked as undisposed after the finalizer has run and the handle has been released. For the Font class, an undisposed instance will just delay the release of the handle until the finalizer runs, but the handle will eventually be released. If possible, it is always a good idea to explicitly Dispose instances that wraps native resources, but it the instances are created internally by the framework or a 3rd-party library, this is not always possible.
SciTech Software AB
Users browsing this forum: No registered users and 27 guests