Link to home
Start Free TrialLog in
Avatar of luiggye
luiggyeFlag for Uruguay

asked on

Why a windows form is not disposed ?

I have a VB NET application.

In a form I am building some charts, using XTRACHARTS library.

All objects inside of that form, was declared PRIVATE.

When I close the form, I need to guarantee that the form IS DISPOSED, in order to release all memory used by it.

Please see the following:

XtraCharts.ShowDialog()
XtraCharts.Dispose()
GC.Collect()
Dim Mem As Process
Mem = Process.GetCurrentProcess()
SetProcessWorkingSetSize(Mem.Handle, -1, -1)
If XtraCharts.IsDisposed Then
   msgbox("The form is not disposed")
End If

XtraCharts.IsDisposed ALLWAYS RETURN FALSE, and memory (a lot memory) used by the charts objects was not released..!!

When I execute:

Dim Mem As Process
Mem = Process.GetCurrentProcess()
SetProcessWorkingSetSize(Mem.Handle, -1, -1)

Ok, the amount of free RAM is increased, because all possible pages in RAM was moved to the page file on the hard disk.

But, when I return to the XtraCharts.ShowDialog(), the performance is very slow, because all pages needed by the XtraCharts objects are moved back from the page file on hard disk to the RAM.

These I/O operations "FREEZE" the application for a long time...!!!.

I made another test:

TestFormWithoutCode.ShowDialog() '----- this form have not any code
TestFormWithoutCode.dispose()
GC.Collect()

If TestFormWithoutCode.IsDisposed Then
   msgbox("The form is not disposed")
End If

TestFormWithoutCode.IsDisposed    ALLWAYS RETURN FALSE TOO..!!

What are happening?

How I can do to REALLY DISPOSE a form?

In my case, I believe that the SetProcessWorkingSetSize(Mem.Handle, -1, -1), is not a good solution (I was found a lot information about it).

I need to find a way to REALLY RELEASE that objects ..!!!!, and the next time I need it, simply create it again, all in memory, of course. I dont want swap to the hard disk that objects...!!!

In my case, I believe that I have 2 options:

1)  Found a way to REALLY CLOSE, DISPOSE, AND REALEASE all objects and resources included inside of XtraCharts form.

2)  Create another VB project XtraCharts, and execute it using Process.Start("XtraCharts.exe")
(Obviously, I will need to pass the source data to build the charts..!! using some xml file, because I  have the source data stored in a grid in the main application).

3) There is a way to RUN the XtraCharts.form in a separate process from the main application and ensure that when it exits, all resources will be released?

I will appreciate any USEFULL COMENTS.
Avatar of Aaron Jabamani
Aaron Jabamani
Flag of United Kingdom of Great Britain and Northern Ireland image

Even though the instance of a control is disposed of, it is still maintained in memory until it is removed from memory through garbage collection.

when you call GC.Collect(0, all objects, regardless of how long they have been in memory, are considered for collection; however, objects that are referenced in managed code are not collected.

You have to do a "Load test"  to see whether your chart objects are not getting cleared. Also you can do for the same logic for some other resource object and see the behaviour.
Avatar of luiggye

ASKER

Thanks Apeter for your comments.

I was made some test and I can tell you the following:

I have 35 forms in my application.

I always am using:

FormXX.showdialog()
FormXX.dispose()
if not FormXX.isDisposed then
   msgbox("Form is not disposed")
endif

Some times, a form is successfully disposed, others not.

Inspecting the source code, I found the following code, only for some forms, not for all form, in the .designer.vb files.

    Inherits System.Windows.Forms.Form

    'Form overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

That code was generated by the Windows Form Designer, but I don't know why was generated for some forms and others not..!!!

Do you know why?

Anyway, that code, not have relation about the dispose success or fail.

Thanks again.



This is a example of a form definition
 
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class frmConditionalFormat
    Inherits System.Windows.Forms.Form
 
    'Form overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub
 
    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer
 
    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.cmbOperators = New System.Windows.Forms.ComboBox
        Me.txtValue1 = New System.Windows.Forms.TextBox
        Me.txtValue2 = New System.Windows.Forms.TextBox
        Me.btnExit = New System.Windows.Forms.Button
        Me.btnFontsColors = New System.Windows.Forms.Button
        Me.fraFormatConditions = New System.Windows.Forms.GroupBox
        Me.lblValue2 = New System.Windows.Forms.Label
        Me.lblValue1 = New System.Windows.Forms.Label
        Me.lblOperators = New System.Windows.Forms.Label
        Me.btnAply = New System.Windows.Forms.Button
        Me.fraFormatConditions.SuspendLayout()
        Me.SuspendLayout()
        '
        'cmbOperators
        '
        Me.cmbOperators.FormattingEnabled = True
        Me.cmbOperators.Location = New System.Drawing.Point(20, 43)
        Me.cmbOperators.Name = "cmbOperators"
        Me.cmbOperators.Size = New System.Drawing.Size(97, 21)
        Me.cmbOperators.TabIndex = 0
        '
        'txtValue1
        '
        Me.txtValue1.Location = New System.Drawing.Point(141, 44)
        Me.txtValue1.Name = "txtValue1"
        Me.txtValue1.Size = New System.Drawing.Size(126, 20)
        Me.txtValue1.TabIndex = 1
        '
        'txtValue2
        '
        Me.txtValue2.Location = New System.Drawing.Point(141, 85)
        Me.txtValue2.Name = "txtValue2"
        Me.txtValue2.Size = New System.Drawing.Size(126, 20)
        Me.txtValue2.TabIndex = 2
        Me.txtValue2.Visible = False
        '
        'btnExit
        '
        Me.btnExit.DialogResult = System.Windows.Forms.DialogResult.Cancel
        Me.btnExit.Location = New System.Drawing.Point(314, 95)
        Me.btnExit.Name = "btnExit"
        Me.btnExit.Size = New System.Drawing.Size(93, 28)
        Me.btnExit.TabIndex = 3
        Me.btnExit.Text = "Exit"
        Me.btnExit.UseVisualStyleBackColor = True
        '
        'btnFontsColors
        '
        Me.btnFontsColors.Location = New System.Drawing.Point(315, 64)
        Me.btnFontsColors.Name = "btnFontsColors"
        Me.btnFontsColors.Size = New System.Drawing.Size(93, 28)
        Me.btnFontsColors.TabIndex = 4
        Me.btnFontsColors.Text = "Fonts/Colors"
        Me.btnFontsColors.UseVisualStyleBackColor = True
        '
        'fraFormatConditions
        '
        Me.fraFormatConditions.Controls.Add(Me.lblValue2)
        Me.fraFormatConditions.Controls.Add(Me.lblValue1)
        Me.fraFormatConditions.Controls.Add(Me.lblOperators)
        Me.fraFormatConditions.Controls.Add(Me.cmbOperators)
        Me.fraFormatConditions.Controls.Add(Me.txtValue1)
        Me.fraFormatConditions.Controls.Add(Me.txtValue2)
        Me.fraFormatConditions.Location = New System.Drawing.Point(16, 18)
        Me.fraFormatConditions.Name = "fraFormatConditions"
        Me.fraFormatConditions.Size = New System.Drawing.Size(284, 125)
        Me.fraFormatConditions.TabIndex = 7
        Me.fraFormatConditions.TabStop = False
        Me.fraFormatConditions.Text = "Format Conditions"
        '
        'lblValue2
        '
        Me.lblValue2.AutoSize = True
        Me.lblValue2.Location = New System.Drawing.Point(138, 69)
        Me.lblValue2.Name = "lblValue2"
        Me.lblValue2.Size = New System.Drawing.Size(34, 13)
        Me.lblValue2.TabIndex = 5
        Me.lblValue2.Text = "Value"
        Me.lblValue2.Visible = False
        '
        'lblValue1
        '
        Me.lblValue1.AutoSize = True
        Me.lblValue1.Location = New System.Drawing.Point(138, 24)
        Me.lblValue1.Name = "lblValue1"
        Me.lblValue1.Size = New System.Drawing.Size(34, 13)
        Me.lblValue1.TabIndex = 4
        Me.lblValue1.Text = "Value"
        '
        'lblOperators
        '
        Me.lblOperators.AutoSize = True
        Me.lblOperators.Location = New System.Drawing.Point(17, 24)
        Me.lblOperators.Name = "lblOperators"
        Me.lblOperators.Size = New System.Drawing.Size(53, 13)
        Me.lblOperators.TabIndex = 3
        Me.lblOperators.Text = "Operators"
        '
        'btnAply
        '
        Me.btnAply.Location = New System.Drawing.Point(314, 32)
        Me.btnAply.Name = "btnAply"
        Me.btnAply.Size = New System.Drawing.Size(93, 28)
        Me.btnAply.TabIndex = 8
        Me.btnAply.Text = "Aply"
        Me.btnAply.UseVisualStyleBackColor = True
        '
        'frmConditionalFormat
        '
        Me.AcceptButton = Me.btnAply
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(419, 162)
        Me.ControlBox = False
        Me.Controls.Add(Me.btnAply)
        Me.Controls.Add(Me.fraFormatConditions)
        Me.Controls.Add(Me.btnExit)
        Me.Controls.Add(Me.btnFontsColors)
        Me.Name = "frmConditionalFormat"
        Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
        Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent
        Me.Text = "Format Conditions Assistant"
        Me.fraFormatConditions.ResumeLayout(False)
        Me.fraFormatConditions.PerformLayout()
        Me.ResumeLayout(False)
 
    End Sub
    Friend WithEvents cmbOperators As System.Windows.Forms.ComboBox
    Friend WithEvents txtValue1 As System.Windows.Forms.TextBox
    Friend WithEvents txtValue2 As System.Windows.Forms.TextBox
    Friend WithEvents btnExit As System.Windows.Forms.Button
    Friend WithEvents btnFontsColors As System.Windows.Forms.Button
    Friend WithEvents fraFormatConditions As System.Windows.Forms.GroupBox
    Friend WithEvents lblValue1 As System.Windows.Forms.Label
    Friend WithEvents lblOperators As System.Windows.Forms.Label
    Friend WithEvents lblValue2 As System.Windows.Forms.Label
    Friend WithEvents btnAply As System.Windows.Forms.Button
End Class

Open in new window

Looks like those set of forms are using some 3rd party or custom componenets. So they have override the dispose method of the form to release the memory of the component. This is the right way to do but the logic should be changed in a standard way like below. And this is not autogenerated code i guess.

Hope after calling your dispose method, your using "GC.SuppressFinalize(Me)" and it should look like below.

Public Overloads Sub Dispose() Implements IDisposable.Dispose
            Dispose(True)
            GC.SuppressFinalize(Me)
        End Sub
        Protected Overrides Sub Finalize()
            Dispose(False)
            MyBase.Finalize()
        End Sub

And your Dispose method should like below.
Protected Overridable Overloads Sub Dispose( _
            ByVal disposing As Boolean)
                If disposing Then
                    components.Dispose()
                End
        End Sub


ASKER CERTIFIED SOLUTION
Avatar of luiggye
luiggye
Flag of Uruguay image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Below i have picked up some definiions from MSDN and hope it gives more clear idea. Sorry for not putting it as code.

Dipose(bool Diposing) disposes of the resources (other than memory) used by the Form. true to release both managed and unmanaged resources; false to release only unmanaged resources.

This method is called by the public Dispose method and the Finalize method. Dispose invokes the protected Dispose(Boolean) method with the disposing parameter set to true. Finalize invokes Dispose with disposing set to false.

When the disposing parameter is true, this method releases all resources held by any managed objects that this Form references, in your case the Charts objects.

Dispose will be called automatically if the form is shown using the Show method. If another method such as ShowDialog is used, or the form is never shown at all, you must call Dispose yourself within your application.

Dispose method is already overriden in our <form>.designer.cs file. We have to just update with our components which we are using in our form. These components are basically "composite" objects in your form.