View previous topic :: View next topic |
Author |
Message |
medbiller
Joined: 20 Dec 2007 Posts: 39 Location: Arroyo, PR
|
Posted: Mon Feb 04, 2013 5:21 pm Post subject: Memory Leak Virtual Tree 4.5.0.0 |
|
|
Hi:
We have a form (frmPatient.vb) which contains 6 vTree controls. We invoke this form (Dim frm as New frmPatient) over & over again for each patient in a clinic. Eventually (usually in the afternoon) we get an Out of Memory runtime error. We verified with PerfMon that Private Bytes and # Bytes in all Heaps keep increasing (never decreasing) even when the opened forms are closed.
We used a tool called .NET Memory Profiler to take a snapshot of memory after opening & closing frmPatient form. Here is the result with respect to frmPatient (the only form opened & closed aside from the Main form):
"Disposed instances with direct delegate roots. This type has one instance that is disposed and still directly rooted by a delegate. This often indicates that the delegate has not been properly removed & may cause memory leak." The delegate appears to be the GetCellDataHandler.
Can you please check this for us. Thanks. _________________ Medical billing & records developer. |
|
Back to top |
|
|
Infralution
Joined: 28 Feb 2005 Posts: 5027
|
Posted: Mon Feb 04, 2013 9:50 pm Post subject: |
|
|
OK - I will check whether there is any issue with this and get back to you tomorrow. _________________ Infralution Support |
|
Back to top |
|
|
Infralution
Joined: 28 Feb 2005 Posts: 5027
|
Posted: Wed Feb 06, 2013 4:17 am Post subject: |
|
|
I modified the Programmatic Binding sample project, which uses the GetCellData event, to add a startup form that has a button to create an instance of the MainForm containing the tree ie:
Code: | public partial class StartForm : Form
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new StartForm());
}
public StartForm()
{
InitializeComponent();
}
private void DisplayForm()
{
MainForm form = new MainForm();
form.ShowDialog();
form.Dispose();
form = null;
}
private void button1_Click(object sender, EventArgs e)
{
DisplayForm();
GC.Collect();
GC.WaitForPendingFinalizers();
}
} |
I then used several different memory profilers (including the one you referred to) to look at the memory usage before and after creating the form by clicking the button. These did not reveal any issues with the MainForm or virtual tree related objects not being disposed. So I don't think the issue is simply Virtual Tree - but probably something to do with how you are using it.
When looking for memory leaks it is a good idea to call GC.Collect and WaitForPendingFinalizers (as the code above does) before taking a snapshot to ensure that you aren't looking at objects that are awaiting garbage collection. Another trick is to strip back your code (if necessary to an empty form and controls) until the leak is no longer occurring and then slowly put functionality back in. _________________ Infralution Support |
|
Back to top |
|
|
medbiller
Joined: 20 Dec 2007 Posts: 39 Location: Arroyo, PR
|
Posted: Wed Feb 06, 2013 2:02 pm Post subject: Memory Leak |
|
|
Hi, thanks for your response:
We cannot call our patient form (frmPatient) as a dialog form ( frmPatient.ShowDialog) because this would cause the application to wait for the user to complete and close this form. Patients would have to be treated on a 1 by 1 exclusive basis and this is not how a clinic works. We must be able to create new instances (Dim frm as New frmPatient) everytime a patient is serviced at the clinics counter. This forms must live in memory for a while as the user switches between patients (each patient is an instance of frmPatient). The user must multitask between the diferent patients being serviced.
So our Main MDI form has a New Patient button that when clicked it executes the following:
Dim frm AS New frmPatient
frm.Show <- CANNOT BE frmPatient.ShowDialog as this would not allow the user to interrupt work in one patient, switch & do work on another patient & then come back to the previous patient to continue.
'frm.Dispose <- cannot be here in Main MDI form which called new instance of frmPatient
'frm=Nothing <- cannot be here in Main MDI form which called new instance of frmPatient
Calling GC.Collect just disrrupts the GC timing process & does the same thing the GC will do automatically by itself sooner or later anyway. This practice is discouraged in the literarture. I think the architecture of your example is very diferent from our production architecture. Hence the profiling results would be like comparing apples to oranges. _________________ Medical billing & records developer. |
|
Back to top |
|
|
Infralution
Joined: 28 Feb 2005 Posts: 5027
|
Posted: Wed Feb 06, 2013 9:57 pm Post subject: |
|
|
I was not advocating using GC.Collect in your real application - just while you are tracking down the leak. As you point out it makes no difference in the long run. However if you don't call it before taking a snapshot with a memory profiler then your snapshop may include objects that are still waiting finalization - which can be quite misleading.
Using ShowDialog or just Show makes absolutely no difference to the way objects are garbage collected. To verify this I modified the same code to use Show instead of ShowDialog and added a second button so I could force a GC.Collect before taking the snapshot.
Code: |
private void launchButton_Click(object sender, EventArgs e)
{
MainForm form = new MainForm();
form.Show();
}
private void gcButton_Click(object sender, EventArgs e)
{
GC.Collect();
GC.WaitForPendingFinalizers();
} |
Taking a snapshot before launching the main form and another after closing the main form revealed no live instance of any Infralution objects.
If you can replicate the leak in a small self contained project (possibly by modifying one of our sample projects) then we would be happy to help further. _________________ Infralution Support |
|
Back to top |
|
|
medbiller
Joined: 20 Dec 2007 Posts: 39 Location: Arroyo, PR
|
Posted: Wed Feb 06, 2013 10:24 pm Post subject: Memory Leak |
|
|
Hi:
We already tried all combinations of GC.Collect with/without GC.WaitForPendingFinalizers, etc. Also Me.Dispose in the FormClosed Event. PerfMon always shows #Bytes in all Heaps & Private Bytes always incrementing never decreasing even after closing all but the main MDI form. # of current logical Threads remains fluctuating normally.
Did you verify how you dispose of the GetCellData event in your source code?
We will try to send you a sample project were this happens. _________________ Medical billing & records developer. |
|
Back to top |
|
|
Infralution
Joined: 28 Feb 2005 Posts: 5027
|
|
Back to top |
|
|
|