I have read a lot of threads that discuss the dispose method, but I haven’t seen any that identify a best practice. Perhaps I didn’t look hard enough. What I don’t understand is how you know when something needs to be disposed. Should you make it a habit to dispose everything that is used by a subroutine that may be used more than once in the lifecycle of the application? Should you also set all of your variables to Nothing so they can be recovered by the GC sooner?

I have an MDI application that at any given time will only have one child open. However, the user has the option of opening any one of over 30 possible children. I instantiate the child in a manner such as:

Code:
Private Sub uiSubComboBox_SelectedValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles uiSubComboBox.SelectedValueChanged

' CLOSE ANY OPEN MDI CHILDREN
Dim frm As Form
For Each frm In Me.MdiChildren
    frm.Close()
Next
' DISPOSE FRM OBJECT
frm.Dispose()

'DETERMINE CONTENTS OF SUB COMBOBOX
If Me.uiMainComboBox.Text = "Bill of Material (BOM)" Then
    If Me.uiSubComboBox.Text = "Maintenance" Then
         Dim bomMaint As New bomMaintForm
         bomMaint.MdiParent = Me
         bomMaint.BlendPanel1.Visible = False
         bomMaint.Show()
         bomMaint.Dock = DockStyle.Fill
         bomMaint.BlendPanel1.Visible = True
         bomMaint = Nothing
As you can see, I have disposed the frm object after the loop because it is no longer needed in the subroutine and will be called many times throughout the lifecycle of the application (Each child is disposed by calling the Close method). Furthermore, I have set the bomMaint variable equal to Nothing after using it to open the child form. As I understand it, this disassociates the child form from the variable, allowing the variable to be picked up by the GC.

In this next example, the routine is simply checking the database for restocking triggers. This routine is called every 15 seconds by a timer. At the bottom of the routine, I have disposed my connection object and my command object. I have also set my variables equal to Nothing.

Code:
Private Sub CheckTriggers()

        Try

            ' CREATE CONNECTION STRING
            Dim invConString As String = _
                    "Provider=Microsoft.Jet.OLEDB.4.0;Data " & _
                    "Source=" & mdbLocation & _
                    "Jet OLEDB:Database Password=******;"

            ' CREATE DATABASE CONNECTION AND OPEN
            invCon = New OleDbConnection(invConString)
            invCon.Open()

            ' CREATE COMMAND
            invCmd = New OleDbCommand("SELECT * FROM invMain WHERE (Inventory <= Trigger)", invCon)

            ' EXECUTE READER
            invRdr = invCmd.ExecuteReader

            If invRdr.HasRows Then
                Me.uiTriggerButton.Enabled = True
                Me.uiTriggerButton.Visible = True
                Me.PictureBox1.Visible = True
                Me.PictureBox2.Visible = False
            Else
                Me.uiTriggerButton.Visible = False
                Me.uiTriggerButton.Enabled = False
                Me.PictureBox1.Visible = False
                Me.PictureBox2.Visible = True
            End If

            ' CLOSE CONNECTIONS
            invRdr.Close()
            invCon.Close()

            ' DISPOSE OBJECTS
            invCon.Dispose()
            invCmd.Dispose()
            invConString = Nothing
            invRdr = Nothing

        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try

    End Sub
So my question to you is “What is the best practice?” Am I even doing this correctly? I have searched for tutorials that deal with disposing objects but have found very few that relate the information to a project that is easy to understand. Surely there must be a good way to learn the best practices of memory management other than reading the MSDN articles.

All responses are appreciated.