Solved

Small app with GDI+ using massive memory resources

Posted on 2004-08-22
9
209 Views
Last Modified: 2011-09-20
hi,

I have a form with not much on it.

the below code is simply drawing 5 lines on a pic box.


*** begin ***
Dim bit As Bitmap = New Bitmap(Pic.Width, Pic.Height)
        Dim g As Graphics = Graphics.FromImage(bit)
        Dim myPen As Pen = New Pen(staffColor, 1)

        'staffline1
        g.DrawLine(myPen, staffStartPosX, staffStartPosY + staffHeight * 2, Pic.Width - 10, staffStartPosY + staffHeight * 2)
        'staffline2
        g.DrawLine(myPen, staffStartPosX, staffStartPosY + staffHeight, Pic.Width - 10, staffStartPosY + staffHeight)
        'staffline3
        g.DrawLine(myPen, staffStartPosX, staffStartPosY, Pic.Width - 10, staffStartPosY)
        'staffline4
        g.DrawLine(myPen, staffStartPosX, staffStartPosY - staffHeight, Pic.Width - 10, staffStartPosY - staffHeight)
        'staffline5
        g.DrawLine(myPen, staffStartPosX, staffStartPosY - staffHeight * 2, Pic.Width - 10, staffStartPosY - staffHeight * 2)

        Pic.Image = bit

        g.Dispose()

*** end ***

Elsewhere on the form, I have a NumericUpDown control which automatically adusts the Staffheight variable from above which would increase the spacing in between the lines....

basically going from this:
________________________
________________________

to:

________________________

________________________


.....

If I adjust the spacing width, the memory for my program increases dramatically.   I have had the very small app go from 50Mb of memory up to 500!!! mb of memory just by moving my mousewheel up and down while in the numericUpDown control.  The memory will eventually readjust itself down to below 100, but that can take up to 30 seconds or so.  Am I doing something wrong with my code?   am I not cleaning up properly?  

I know there is some kind of garbage collector that automatically cleans up destroyed objects, but it seems to only happen every few seconds, or not enough.   I'm assuming the culprits that are filling up the memory are the bitmaps that are being created in the above routine simply because they aren't being destroyed fast enough by the automatic .net garbage collector.

thx.


0
Comment
Question by:OnlineGuitarist
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
  • 2
9 Comments
 
LVL 14

Assisted Solution

by:ptakja
ptakja earned 100 total points
ID: 11866623
The PictureBox control has a ton of overhead associated with it to support the varying types of images.  It was not intended to have developers drawing in the image surface using GDI+, although that is supported as well, as you have seen.

I would recommend replacing the PictureBox control with a Panel control and drawing your graphics in the Panel control.  You are not limited to only pixel graphics either.  You can load a bitmap from a file and use GDI+ to draw the image to the panel using the DrawImage method of the graphics class.

Do your painting in the Panel's Paint event handler to get your graphcis to remain persistent when the window is moved or covered by another window.

Jeff
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 11866998
>> am I not cleaning up properly?  

Anytime YOU create an Image, Bitmap, Graphic, Pen or Brush, you should call the dispose method and set the variable to Nothing to release the memory and speed up garbage collection when you are through with it.

        bit.Dispose()
        bit = Nothing
        myPen.Dispose()
        myPen = Nothing
        g.Dispose()
        g = Nothing

Regards,

Idle_Mind
0
 

Author Comment

by:OnlineGuitarist
ID: 11870798
bit.dispose causes errors in my program.   as soon as it's called the area where the bitmap is suppose to appear is blank, and the program halts with a generic error:

An unhandled exception of type 'System.ArgumentException' occurred in system.windows.forms.dll

Additional information: Invalid parameter used.


upon commenting out bit.dispose and bit = nothing, the program functions as normally.  myPen.dispose and g.dispose work fine.
0
Online Training Solution

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action. Forget about retraining and skyrocket knowledge retention rates.

 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 11870862
Can you show us the complete code where you draw and how you cause the lines to be updated?

Idle_Mind
0
 

Author Comment

by:OnlineGuitarist
ID: 11870891
Private Sub pic_Resize(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Pic.Resize
        If Pic.Width >= 1 And Pic.Height >= 1 Then
            Dim bit As Bitmap = New Bitmap(Pic.Width, Pic.Height)
            Dim g As Graphics = Graphics.FromImage(bit)
            g.Clear(Pic.BackColor)

            bit.Dispose()
            bit = Nothing
            g.Dispose()
            g = Nothing

            pnlNotationDrawGrid()

        End If
    End Sub

Private Sub pnlNotationDrawGrid()

        'Draw line on picturebox
        'Put a picturebox on the form named pic
        Dim i As Short = PrivateVarIntStaffHeight
        i = i + 7
        Dim bit As Bitmap = New Bitmap(Pic.Width, Pic.Height)
        Dim g As Graphics = Graphics.FromImage(bit)
        Dim myPen As Pen = New Pen(PrivateVarColStaffColor, 1)

        'staffline1
        g.DrawLine(myPen, PrivateVarIntStaffStartPosX, PrivateVarIntStaffStartPosY + i * 2, Pic.Width - 10, PrivateVarIntStaffStartPosY + i * 2)
        'staffline2
        g.DrawLine(myPen, PrivateVarIntStaffStartPosX, PrivateVarIntStaffStartPosY + i, Pic.Width - 10, PrivateVarIntStaffStartPosY + i)
        'staffline3
        g.DrawLine(myPen, PrivateVarIntStaffStartPosX, PrivateVarIntStaffStartPosY, Pic.Width - 10, PrivateVarIntStaffStartPosY)
        'staffline4
        g.DrawLine(myPen, PrivateVarIntStaffStartPosX, PrivateVarIntStaffStartPosY - i, Pic.Width - 10, PrivateVarIntStaffStartPosY - i)
        'staffline5
        g.DrawLine(myPen, PrivateVarIntStaffStartPosX, PrivateVarIntStaffStartPosY - i * 2, Pic.Width - 10, PrivateVarIntStaffStartPosY - i * 2)

        Pic.Image = bit

        'bit.Dispose()
        'bit = Nothing
        myPen.Dispose()
        myPen = Nothing
        g.Dispose()
        g = Nothing

    End Sub

0
 
LVL 86

Accepted Solution

by:
Mike Tomlinson earned 115 total points
ID: 11871279
It should be more like this:

    Private Sub pic_Resize(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Pic.Resize
        Pic.Refresh()
    End Sub

    Private Sub Pic_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Pic.Paint
        If Pic.Width >= 1 And Pic.Height >= 1 Then
            Dim g As Graphics = e.Graphics
            Dim myPen As Pen = New Pen(PrivateVarColStaffColor, 1)

            g.Clear(Pic.BackColor)

            'staffline1
            g.DrawLine(myPen, PrivateVarIntStaffStartPosX, PrivateVarIntStaffStartPosY + i * 2, Pic.Width - 10, PrivateVarIntStaffStartPosY + i * 2)
            'staffline2
            g.DrawLine(myPen, PrivateVarIntStaffStartPosX, PrivateVarIntStaffStartPosY + i, Pic.Width - 10, PrivateVarIntStaffStartPosY + i)
            'staffline3
            g.DrawLine(myPen, PrivateVarIntStaffStartPosX, PrivateVarIntStaffStartPosY, Pic.Width - 10, PrivateVarIntStaffStartPosY)
            'staffline4
            g.DrawLine(myPen, PrivateVarIntStaffStartPosX, PrivateVarIntStaffStartPosY - i, Pic.Width - 10, PrivateVarIntStaffStartPosY - i)
            'staffline5
            g.DrawLine(myPen, PrivateVarIntStaffStartPosX, PrivateVarIntStaffStartPosY - i * 2, Pic.Width - 10, PrivateVarIntStaffStartPosY - i * 2)

            myPen.Dispose()
            myPen = Nothing
        End If
    End Sub

Regards,

Idle_Mind
0
 
LVL 14

Expert Comment

by:ptakja
ID: 11871321
Have you tried painting a Panel control instead of a Picturebox?
0
 

Author Comment

by:OnlineGuitarist
ID: 11871464
Ok, I tried the suggestions earlier, however I wasn't aware of the refresh method which is why I used the bitmaps.  I've taken out the pic box and replaced with a panel control, along with the suggested draw methods using only the pen.   Since I tried this before with out the .refresh methods, I was having trouble with the graphics updating.   With this new info, the program is staying at 20mb or so while performing the same operation that was causing the program to run up to the 500mb mark.

thx so much!

I'll give every point i have, try to split it between you two accordingly.
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 11871490
Glad we got it working correctly!  

=)
Idle_Mind
0

Featured Post

PeopleSoft Has Never Been Easier

PeopleSoft Adoption Made Smooth & Simple!

On-The-Job Training Is made Intuitive & Easy With WalkMe's On-Screen Guidance Tool.  Claim Your Free WalkMe Account Now

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
VB.Net creating Contact in Outlook 1 96
Send SMS from vb.net desktop app 30 51
Best book for Internet security 4 52
Run software updates from the website 6 50
Since .Net 2.0, Visual Basic has made it easy to create a splash screen and set it via the "Splash Screen" drop down in the Project Properties.  A splash screen set in this manner is automatically created, displayed and closed by the framework itsel…
1.0 - Introduction Converting Visual Basic 6.0 (VB6) to Visual Basic 2008+ (VB.NET). If ever there was a subject full of murkiness and bad decisions, it is this one!   The first problem seems to be that people considering this task of converting…
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…

732 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question