kgoodrich Posted December 8, 2006 Posted December 8, 2006 I have an application in which I am trying to work some bugs out of. I have started out by using the .NET Profiler in order to try and track down some memory problems. That is somewhat working as I have found the cause of a few and still have quite a few to go. Another problem is that while my application is running and I am opening and closing windows, my handle count(viewable through the task manager) continuously goes up and never comes down. I ran Handle by SysInternals and determined that it looks like the handles that keep going up and never coming back down are Mutant handles(I guess this means mutex handles). How can I track down this problem and what to do about it. This is a C# windows application. Thanks, Kendal Quote
*Experts* Nerseus Posted December 8, 2006 *Experts* Posted December 8, 2006 A form is just a class that contains references to valuable resources (handles) that need to be released quickly. Standard .NET will just mark a class for cleanup when it goes out of scope, such as when a form closes. If you have known resources, you're supposed to implement the Dispose pattern to clean up those resources. Most books talk about files and printers and neglect to talk about the much more common window handles - you get one per control, more or less, so they add up fast. My company uses a base form that takes care of cleaning itself up, along with the proper dispose code. It's part of a framework, so showing you my code snippets wouldn't be very useful. I can recommend finding out how to implement Dispose, if you don't know already of course. In Dispose for a form, make sure you call dispose on all controls and other resources (if any). The key is also making sure you call Dispose on your form, so that the Dispose method disposes the controls. I think we put this in the Closed event, but I can't recall offhand. -ner Quote "I want to stand as close to the edge as I can without going over. Out on the edge you see all the kinds of things you can't see from the center." - Kurt Vonnegut
kgoodrich Posted December 8, 2006 Author Posted December 8, 2006 By default, when a form is closed, the dispose method is called, therefore disposing all controls on the form. There is no doubt that the form is getting diposed and garbage collected. The reason I know this is that I used the .NET Profiler to take some snapshots before I opened the form. I then opened and closed the form and took another snapshot. There were no references to the specific form, but my handle count went up by 10 and did not come back down. The handle count continually goes up and never comes back down. Using Handle by SysInternals I was able to find out that the handle that keeps going up and not coming back down is of type Mutant. What is a mutex handle and how are they being allocated???? What can I do about this?????? Quote
Leaders snarfblam Posted December 8, 2006 Leaders Posted December 8, 2006 Firstly, what is Mutant? It sounds like it would describe something that has changed (mutate). As far as I know that is not a synonym for mutex. Mutex is an abbreviation for "mutually exclusive." Secondly, when you say handles, do you mean handles to Windows resources or references to .Net objects? Over what period of time are you observing this behavior? Are you doing anything that might interfere with garbage collection? Are you forcing any garbage collections? Are you using third party components? Who makes the components? Are you using any objects that are disposable that you aren't disposing? What I really recommend you do is go over you code and be very familiar with where you allocate what. Consider refactoring. Simplify and unify code. It will make it easier to identify where resources are allocated and which resources might not be de-allocated. Quote [sIGPIC]e[/sIGPIC]
Administrators PlausiblyDamp Posted December 8, 2006 Administrators Posted December 8, 2006 A Mutant (in this case anyway) is the NT Kernel equivalent of a Mutex. When you are looking at the Profiler does it show which method(s) are allocating these handles? Are you doing anything with threading yourself (either directly or via the various async methods i.e. BeginXXXXX and EndXXXXX functions)? Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
kgoodrich Posted December 11, 2006 Author Posted December 11, 2006 That is part of my problem. I have not found any place that talks about Mutant handles. But using Handle by SysInternals to find out how many handles of each type are open.....it lists Mutant type handles in the list. All I do is open and close one of my forms and the Mutant handle count increases by 10 and never decreases. I am not using any 3rd party controls. I am using some custom controls built off of NET controls. Quote
Administrators PlausiblyDamp Posted December 11, 2006 Administrators Posted December 11, 2006 Does this form you are opening and closing instantiate any of these customer controls? If so which controls are they built off? Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
kgoodrich Posted December 11, 2006 Author Posted December 11, 2006 (edited) UPDATE: I just found out what is specifically causing my handle count to increase....It is Microsoft's InkOverlay class. I am using this class because this application will be running on a tablet as well as a desktop. I was not specifically disposing of the InkOverlay object. I use a custom RichTextBox that incorporates the InkOverlay class. In the RichTextBox's dispose method I tried to dispose of the InkOverlay instance. Now when the form is instantiated, my handle count goes up by 10 and when I close the form, the handle count drops by 5. So I still have a problem with 5 handles not being removed. If I was to comment out the code that creates a new instance of InkOverlay, my handle count would not go up or down. Any suggestions about using the inkoverlay class???? Edited December 11, 2006 by kgoodrich Quote
Administrators PlausiblyDamp Posted December 13, 2006 Administrators Posted December 13, 2006 (edited) Have a look at http://msdn2.microsoft.com/en-us/library/ms833057.aspx - just after the syntax declarations it warns you make sure you explicitly call .Dispose on any instances of the class to prevent a handle leak. Might be worth doing that and checking to see if the problem goes away. Edited December 14, 2006 by PlausiblyDamp Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
kgoodrich Posted December 13, 2006 Author Posted December 13, 2006 That is what I do. I specifically call the dispose method of the inkobject. That actually dropped my handle count from 10 to 5. It appears that the InkOverlay object is creating 10 handles and when I explicitly dispose fo the InkOverlay object, only 5 of those handles are getting released. Any suggestions?????????????? Quote
Administrators PlausiblyDamp Posted December 13, 2006 Administrators Posted December 13, 2006 Could you post the code for the form's load event or which events you are creating and disposing of the InkOverlay class? Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
kgoodrich Posted December 13, 2006 Author Posted December 13, 2006 (edited) To test this theory at minimum, I created a form with no controls and an instance of InkOverlay. The form is listed below: public class Test : System.Windows.Forms.Form { private System.ComponentModel.Container components = null; public InkOverlay oInk; public Test() { InitializeComponent(); oInk = new InkOverlay(); } protected override void Dispose( bool disposing ) { oInk.Dispose(); if( disposing ) { if(components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { // // Test // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(816, 446); this.Name = "Test"; this.Text = "Test"; } #endregion } With this form, all I do is show the form and close it. The handles increase by 10 when opened and decreased by 5 when closed, leaving 5 handle that are never released. Edited December 13, 2006 by PlausiblyDamp Quote
*Experts* Nerseus Posted December 14, 2006 *Experts* Posted December 14, 2006 It looks like you're doing everything right. Just to be clear, did you try GC.Collect() after the form is closed, before you ran the SysInternal check, to make sure the form was disposed? A form normally won't get disposed right away and I wonder if a SysInternals check would show 5 handles used, until the form is completely disposed. If the answer is "yes, the form is Disposed" then I can't think of anything else to try on your own. You can always put in a support call to MS. If you have an MSDN subscription then you may get a few free ones (you used to, I haven't looked in awhile). My experience with their support calls is mixed - you'll definitely get some kind of noob at first, but if you provide a sample app that experiences the memory leak and solid proof, you can usually get things escalated until you get an answer. -ner Quote "I want to stand as close to the edge as I can without going over. Out on the edge you see all the kinds of things you can't see from the center." - Kurt Vonnegut
Leaders snarfblam Posted December 14, 2006 Leaders Posted December 14, 2006 I am nearly certain (unfortunately, I'm too lazy to check) that a form is disposed when the user closes the form, unless you intercept the form close, cancel it, and hide the form. Quote [sIGPIC]e[/sIGPIC]
*Experts* Nerseus Posted December 15, 2006 *Experts* Posted December 15, 2006 Nope, the exact opposite is true. A form is not disposed unless you call Dispose. That's how you're able to retrieve the form's properties even after a form is closed (on a modal form for example). A standard pattern is to have a form self-dispose in a Closed event, or have a "window/form manager" do that for you. Since the handles are going down, I was guessing he was calling Dispose - at least set a breakpoint in the method to see that it's getting called. -ner Quote "I want to stand as close to the edge as I can without going over. Out on the edge you see all the kinds of things you can't see from the center." - Kurt Vonnegut
Leaders snarfblam Posted December 16, 2006 Leaders Posted December 16, 2006 Well, call me crazy, but when I worked up enough energy to open VB and test my previous statement, I ran into results contrary to what you stated (i.e. in agreement with my original understanding). In a VB winforms app, with one form named Form1 containing one button named Button1, I used the following code: Public Class Form1 Dim theform As Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click If (theform Is Nothing) Then theform = New Form1() End If theform.Show() End Sub End Class When I click the button, close the new form, then click the button again (which will attempt to re-show the form) I get an ObjectDisposedException. Now, that an exception occurs is understandable. One might expect that Windows resources are freed when a window is closed, even if it is not disposed, but that the exception explicitly states that the object is disposed, well, I guess that's my point. Keep in mind that there is not necessarily any reason why certain properties of any IDisposable object can't be read after said object is disposed. When you create an IDisposable object, do you add a check in all properties to see if the object is disposed? In fact, when I modified the code to: Public Class Form1 Dim theform As Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click [i] If (Not theform Is Nothing) Then MessageBox.Show(theform.IsDisposed.ToString()) End If[/i] If (theform Is Nothing) Then theform = New Form1() End If theform.Show() End Sub End Class The output did indicate that the form had been disposed. Quote [sIGPIC]e[/sIGPIC]
*Experts* Nerseus Posted December 16, 2006 *Experts* Posted December 16, 2006 My mistake - sorry to anyone reading this. I was thinking of modal forms (using ShowDialog), which don't dispose and shouldn't (otherwise you couldn't access them later). -ners Quote "I want to stand as close to the edge as I can without going over. Out on the edge you see all the kinds of things you can't see from the center." - Kurt Vonnegut
kgoodrich Posted December 18, 2006 Author Posted December 18, 2006 Does this look like a bug with .NET???? I don't have a subscription to MSDN, so what are my options????? Does anyone have any other suggestions?????? Quote
alreadyused Posted December 18, 2006 Posted December 18, 2006 (edited) disposing I'm posting to this thread specifically because of the discussion between MarbleEater and Nerseus about disposing, especially in regards to a form. I've been reading a lot about disposing lately and have to say I definately have questions and I'm sure plenty of misconceptions and misunderstandings. Without rambling on, somewhere in this forum somebody suggested reading this: http://www.gotdotnet.com/team/libraries/whitepapers/resourcemanagement/resourcemanagement.aspx That does a very good job of explaining it, and maybe I'm just slow, but I still have questions. Basically, I guess what I'm looking for is a concise FAQ or tutorial on disposing that sums up the majority of it. I think that would be extremely beneficial for many people and would hopefully lead to our community having a better understanding. The following are items that I'm aware of (and have either a clear or fuzzy understanding of), and I know there's a lot more that could/should be added to the list: When to handle the GC versus when not to What category (managed/unmanaged) some of the most common controls fall into How to test whether an object should be disposed How to properly write a disposing method on classes with unmanaged resources Simple tests to determine if your objects are being released from memory Differences between C# and VB on disposing So, that being said, I've looked for something like that and haven't been able to find anything. Does anyone know of one, or would one of the more advanced members or mods feel like taking a stab at that and making it a sticky? Or do I just need to buy a book and/or go back to school? :-D Edited December 18, 2006 by alreadyused Quote
Leaders snarfblam Posted December 18, 2006 Leaders Posted December 18, 2006 Sorry if we are pulling the thread a little off topic. I will see what, if anything, there is in the tutor's corner about the GC and disposable objects (and probably add a thread on the topic). Any further discussion on the topic where it does not pertain the the original post will hopefully go there or in random thoughts. Quote [sIGPIC]e[/sIGPIC]
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.