Why does dispose() not make second instantiation of an object go away?

I'm writing a program in VB 2005 Express Beta 2.  The code pasted at the end of this note is a simplified example of a problem I am having in a more complex piece of code.  The simple code does the following: I have a startup form (called Form1) with two buttons on it.  Button1 triggers a loop ranging from 0 to 9 to create 10 new instances of a picturebox (all in a 10-element picturebox array called picbox) by setting all the necessary parameters (location, size, image, etc) to display the same picture 10 times across the client area of Form1.  Button2 triggers another loop (in its click event handler) ranging from 0 to 9 which simply applies the Dispose() method to each instance of a picturebox in the array picbox.

The code which does all this is pasted below for review.  If I run the program and press Button1 once, I get ten images splashed across the client area of Form1, as desired.  If I immediately thereafter press Button2 once, those ten images disappear - which is also what I want.  And of course if I were to run the program and initiallypress Button2 once (before having pressed Button1) the program crashes and I get an exception - I understand why that happens, because no instance has been created for the Dispose() method to act upon.

My question/problem is this:  If I run the program and happen to press Button1 two or more times in a row, the images appear as desired, but no amount of clicking on Button2 will make them go away.  Neither will putting a command in the Button2 loop to set the visible property to false of each picturebox in the picbox array work either (although I think, for other reasons in my more complex code, that I want the pictureboxes to go away entirely, not just to be invisible).

Obviously there is something I don't understand about instantiating the same named object a second (or third, fourth, etc) time.  Why does Dispose() not act the same way (or multiple runnings of Dispose() on the same object)   Does instantiating an object more than once make it resistant to garbage collection   Or is this just one of those many things about graphics objects that I just don't understand   Is there a stronger garbage collection method than Dispose(), something that actually makes the program completely forget that an instantiation has taken place   Fundamentally I just want to have a button that makes these pictureboxes disappear, no matter how many times the user may press (inadvertently or otherwise) the button that instantiates those picturebox objects.  Any thoughts   The code for the simple example that recreates this problem is pasted below.  Thanks for any help.

Public Class Form1

Dim picbox() As PictureBox

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

ReDim picbox(0 To 9)

For i As Integer = 0 To 9

picbox(i) = New PictureBox

Me.Controls.Add(picbox(i))

picbox(i).Size = New Size(71, 96)

picbox(i).Image = Bitmap.FromFile("f:\graphics\cards\sk.gif")

picbox(i).Visible = True

picbox(i).Location = New Point(10 + 80 * i, 100)

Next

End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

For i As Integer = 0 To 9

picbox(i).Visible = False

picbox(i).Dispose()

Next

End Sub

End Class






Answer this question

Why does dispose() not make second instantiation of an object go away?

  • Angal

    Hi,

    In case you press Button1 twice or more, then press Button2 trying to clean up; the picture boxes do not go away because Dispose is being called on the wrong picture boxes.
    - First time you press Button1, 10 picture boxes are created and added to the Form's Controls collection. Let's call them PB1 .. PB10. picbox array has references to them.
    - Second time you press Button1, 10 DIFFERENT picture boxes are created and added to the Form's Controls collection. Let's call them PB11 .. PB20. At this time picbox array only has references to PB11 .. PB20. Only the Form's Controls collection has references to PB1 .. PB10 now.
    - No matter how many times you press Button2, the code only disposes PB11 .. PB20, PB1 .. PB10 are still there and being displayed on Form1.

    A quick way to really clean these is to use this code at the beginning of Button1 and Button2 event handler.

    If picbox IsNot Nothing Then
       
    For Each pic As PictureBox In
    picbox
           
    If Me.Controls.Contains(pic)
    Then
               
    Me
    .Controls.Remove(pic)
           
    End
    If
       
    Next
    End If

    This way the picture boxes are really removed from the Form's Controls collection.

    Hope this helps, regards.



  • Kelvin Tse

    "picbox(i).Image = Bitmap.FromFile("f:\graphics\cards\sk.gif")"


    Hmmmmm.

    In reading up on images and bitmaps, from what I can see is that these images are kept open until they are disposed of. They are very stubborn about that.

    For educational purposes, what would happen if you made SK.gif am internal resource instead of an open file. WHat would happen if you moved it to an imagelist

    I'm not sure that this is your problem, but this really jumped out at me when I saw it.



  • Why does dispose() not make second instantiation of an object go away?