locked
GDI Drawings freezing after a few minutes RRS feed

  • Question

  • Currently in our program we create bitmaps to use on picture boxes to draw graphs and sketches.  We create a bitmap and then use the creategraphics function to begin drawing, creating a new bitmap and disposing of the old when we need to resize.    We then set the Image property of the Picturebox to the bitmap after completion.  The problem is after a few minutes of the program being up occasionally the graphics stop drawing.  They just freeze at the last drawing and stop updating.  Sometimes the Picturebox displays the red X and occasionally we get an unhandled exception in the ondraw command of the picturebox, which we don't use, but most of the time it freezes and just stops drawing.  What could be causing this?  Is there anything we can do to prevent this?

    frmMain1.TensionChart.BackgroundImage = Nothing
    If Height = -1 Or Width = -1 Then
    	MainBelt.CurrentCase.TenPlotDrawer.Resize(frmMain1.TensionChart.Width, frmMain1.TensionChart.Height)
    Else
    	MainBelt.CurrentCase.TenPlotDrawer.Resize(Width, Height)
    End If
    frmMain1.TensionChart.BackgroundImage = MainBelt.CurrentCase.TenPlotDrawer.nImage
    MainBelt.TenPlot(MainBelt.CurrentCase.TenPlotDrawer, MainBelt.CurrentCaseIndex, Color.White, , , False)
    frmMain1.TensionChart.BackgroundImageLayout = ImageLayout.Zoom
    frmMain1.TensionChart.Refresh()
    TenPlotDrawer is  structure with a bitmap, and a graphics class along with a brush and a pen.  Its just something to bundle them all together.  TensionChart is a Picturebox.  Resize on TenPlotDrawer just resizes the bitmap creates a new graphics

    Public Sub Resize(ByVal Width As Integer, ByVal Height As Integer)
    	Try
    		If nImage.Width = Width And nImage.Height = Height Then Exit Sub
    		If Not nImage Is Nothing Then nImage.Dispose() : nImage = Nothing
    		If Not nDrawer Is Nothing Then nDrawer.Dispose() : nDrawer = Nothing : GC.Collect()
    		nImage = New System.Drawing.Bitmap(Width, Height)
    		nDrawer = Graphics.FromImage(nImage)
    	Catch ex As Exception
    		CheckValid()
    	End Try
    End Sub
    
    
    Public Sub CheckValid()
    	Try
    		If nImage Is Nothing Or nDrawer Is Nothing Then
    			nImage = New System.Drawing.Bitmap(300, 300)
    			nDrawer = Graphics.FromImage(nImage) : GC.Collect()
    		End If
    		If nImage.Width = 0 Or nImage.Height = 0 Then
    			nImage = New System.Drawing.Bitmap(300, 300)
    			nDrawer = Graphics.FromImage(nImage) : GC.Collect()
    		End If
    	Catch ex As Exception
    		nImage = New System.Drawing.Bitmap(300, 300)
    		nDrawer = Graphics.FromImage(nImage) : GC.Collect()
    	End Try
    End Sub

    Thursday, May 8, 2014 4:12 PM

Answers

  • Oh the GC.Collect()... doing more harm than good for most time. Since it's a blocking function, your code can do nothing before it finishes.

    Except in some extremely rare case, it's always better to let the runtime decide when to collect the garbage.


    Friday, May 9, 2014 2:52 AM
    Answerer

All replies

  • Try these things:

    • Remove the nDrawer member. Use a local variable, only during re-creation of image. Use ‘Using’ statement to dispose it automatically (no need to call Dispose explicitly).
    • Before re-creation of the image, assign Nothing to BackgroundImage. Then dispose the old image, and then create the new one, and assign to BackgroundImage.
    • Remove calls to GC.Collect.
    Thursday, May 8, 2014 6:18 PM
  • Oh the GC.Collect()... doing more harm than good for most time. Since it's a blocking function, your code can do nothing before it finishes.

    Except in some extremely rare case, it's always better to let the runtime decide when to collect the garbage.


    Friday, May 9, 2014 2:52 AM
    Answerer