Problems with GDI objects

  • Thread starter Jonathan Boivin
  • Start date
J

Jonathan Boivin

Hi,

I've got some problems with loading bills using a bill usercontrol I built.
If I load all current bills in my test environment (156) everything is fine
once, but repeating the operation (which clear all the bills and reshow all
of them) four to five times and I get a Error creating window handle. I
investigated on all of this, a lot, and still I'm not able to find where
this problem come from. I know that the GDI objects column in the task
manager gives me growing and growing number up to 10000 max and then crash.

http://www.cints.net/clinica/LoadFactures.jpg
http://www.cints.net/clinica/LoadFactures-Opened.jpg

I put there two pictures which shows you how looks like the form which cause
me the problem (this is a MDI application, i dont know if it's important).
The second one brings on details about hidden part of the bill usercontrol.
This is to give you an idea about how many controls there is on this
usercontrol, but be advised that I recently transform everything possible
into Graphics.DrawString calls which use Brushes.Black as brush and a font
which I dispose or pens which are disposed too. This saved me on the number
of handle created, but still,
there's a lot and more, I got a problem with those GDI objects.

So, let me show you numbers I collected from the task manager.
USER Objets / GDI Objets
100/178=Main window loaded
149/194=Bills window loaded
4522/1817=All bills loaded (156) (1st time)
4616/3432=All bills loaded (156) (2nd time)
4710/5047=All bills loaded (156) (3rd time)
390/5042=Bills window closed

100/178=Main window loaded
149/192=Bills window loaded
102/186=Bills window closed

As you can see,these numbers are alarmous (lol, to me though). The number of
GDI objects never goes down significativily. Even opening the window only
and closing doesn't make the number going back to normal. Let's consider
that the numbers of the last three lines are normal (if I able to fix the
big one, small one should be easy to find).

I tried to use a profiler, but where nothing helps me find the solution
(because I tried lots of thing, I ameliorate too during the process).

So my questions are : How could I trace these GDI objects in my code ? Is
there a list of GDI objects type (complete) which could tells me what I
didn't disposed (because i'm about to dispose strings.. lol) (like I know
that Pen, brushes, bitmap, graphics as to be disposed)?

Thank you for reading up to there. I'm sorry for mistakes, I don't use my
english often.
One of your french quebeceer friend who desparatly needs help!
 
T

Tom Shelton

Hi,

I've got some problems with loading bills using a bill usercontrol I built.
If I load all current bills in my test environment (156) everything is fine
once, but repeating the operation (which clear all the bills and reshow all
of them) four to five times and I get a Error creating window handle. I
investigated on all of this, a lot, and still I'm not able to find where
this problem come from. I know that the GDI objects column in the task
manager gives me growing and growing number up to 10000 max and then crash.

You clear the controls? How? Are you actually disposing of the user
controls and dyanmaically creating new ones?
 
J

Jonathan Boivin

Yes, I dispose and remove all handlers and objects. Here is the piece of
code to clean everything before generating dynamically all usercontrols,
buttons and checkboxes.

For i = FacturesPanel.Controls.Count - 1 To 0 Step -1
If TypeOf (FacturesPanel.Controls(i)) Is CheckBox Then
RemoveHandler CType(FacturesPanel.Controls(i), CheckBox).CheckedChanged,
AddressOf FacturationBoxCheck_CheckedChanged
If FacturesPanel.Controls(i).Name.StartsWith("PBButton") Then
RemoveHandler CType(FacturesPanel.Controls(i), Button).Click, AddressOf
FacturationBoxEnableStop_Click
If FacturesPanel.Controls(i).Name.StartsWith("UnifyButton") Then
RemoveHandler CType(FacturesPanel.Controls(i), Button).Click, AddressOf
FacturationBoxUnify_Click
If FacturesPanel.Controls(i).Name.StartsWith("DUButton") Then
RemoveHandler CType(FacturesPanel.Controls(i), Button).Click, AddressOf
FacturationBoxDesunify_Click
If FacturesPanel.Controls(i).Name.StartsWith("CRButton") Then
RemoveHandler CType(FacturesPanel.Controls(i), Button).Click, AddressOf
FacturationBoxCreateRecu_Click
FacturesPanel.Controls(i).Dispose()
Next i
FacturesPanel.Controls.Clear()
GC.Collect()
 
T

Tom Shelton

Yes, I dispose and remove all handlers and objects. Here is the piece of
code to clean everything before generating dynamically all usercontrols,
buttons and checkboxes.

For i = FacturesPanel.Controls.Count - 1 To 0 Step -1
If TypeOf (FacturesPanel.Controls(i)) Is CheckBox Then
RemoveHandler CType(FacturesPanel.Controls(i), CheckBox).CheckedChanged,
AddressOf FacturationBoxCheck_CheckedChanged
If FacturesPanel.Controls(i).Name.StartsWith("PBButton") Then
RemoveHandler CType(FacturesPanel.Controls(i), Button).Click, AddressOf
FacturationBoxEnableStop_Click
If FacturesPanel.Controls(i).Name.StartsWith("UnifyButton") Then
RemoveHandler CType(FacturesPanel.Controls(i), Button).Click, AddressOf
FacturationBoxUnify_Click
If FacturesPanel.Controls(i).Name.StartsWith("DUButton") Then
RemoveHandler CType(FacturesPanel.Controls(i), Button).Click, AddressOf
FacturationBoxDesunify_Click
If FacturesPanel.Controls(i).Name.StartsWith("CRButton") Then
RemoveHandler CType(FacturesPanel.Controls(i), Button).Click, AddressOf
FacturationBoxCreateRecu_Click
FacturesPanel.Controls(i).Dispose()
Next i
FacturesPanel.Controls.Clear()
GC.Collect()


Really, without sitting down with the app and looking it over, this is
a really hard porblem to solve. All I can do is really just sit here
and see if I can think of places that may be problematic. You say you
ran a profiler? It didn't give you any clue as to what objects were
still alive? I've used the Ants Profiler a couple of times with great
success http://www.red-gate.com/products/dotnet_tools_overview.htm.
Are you doing a lot of custom drawing? Because if you are, and you
aren't properly cleaning up your graphic objects, you can be leaving a
lot of unmanaged resources...
 
J

Jonathan Boivin

Hi Tom,

I tried ANTS profiler and I'm not able to find out how to get the info I
want. I read the help to give me a clue, but I'm not able to understand how
to get what I want. I would like to see objects which are still alive, but
not those coming from the first snapshot (which I do right before showing
the bills). So I'd be probably able to see what wasn't disposed and start to
find a solution. So, I don't know if you're able to give a clue on this ?
Otherwise, maybe would you like from me to give you the snapshots so you
could look yourself ?

About the custom drawing, all the texts is printed within the Paint method
of the appropriate object (because the bill usercontrol is built from
multiple controls & usercontrols). The only reel custom drawing I'm doing is
coming from my own built list (see $Test-LoadFactures-Opened.jpg), but I
think this usercontrol has been optimized & corrected so there shouldn't be
any problem coming from it (I reverified to be sure). Except this one, all
other controls are derived from Microsoft controls or directly Microsoft
controls.

Here are new numbers by removing some parts of the bill usercontrol :
Objects USER / Objects GDI
100/178=Main win loaded
149/194=Win Gestion des factures loaded
4522/1817=All bills loaded (156) (1st) (W/O pics --> 633 GDI) (W/O
Histories --> 1053 GDI) (W/O Histos + W/O Hidden part --> 196 GDI)
4616/3432=All bills loaded (156) (2st) (W/O pics --> 1103 GDI.. BUG) (W/O
Histos --> 1908 GDI) (W/O Histos + W/O Hidden part --> 196 GDI)
4710/5047=All bills loaded (156) (3rd) (W/O Histos --> 2763 GDI) (W/O
Histos + W/O Hidden part --> 196 GDI)
390/5042=Win Gestion des factures closed (W/O Histos --> 2755 GDI) (W/O
Histos + W/O Hidden part --> 188 GDI)

My pictures are coming from a DrawingManager I made which stores all images,
icons & cursors.

Thank you, Tom, for you help. This project is a bit complex, mostly due to
the fact that it has been transported from VB6, Files saving format to
VB.NET, SQL Server. Though, I didn't have this problem with VB6.

I was wondering too, is the use of string concatenation is a good pratice or
not ? Are the strings created on the fly are cleaned up after the method is
finished (hopely so) ?
 
T

Tom Shelton

Hi Tom,

I tried ANTS profiler and I'm not able to find out how to get the info I
want. I read the help to give me a clue, but I'm not able to understand how
to get what I want. I would like to see objects which are still alive, but
not those coming from the first snapshot (which I do right before showing
the bills). So I'd be probably able to see what wasn't disposed and startto
find a solution. So, I don't know if you're able to give a clue on this ?
Otherwise, maybe would you like from me to give you the snapshots so you
could look yourself ?

About the custom drawing, all the texts is printed within the Paint method
of the appropriate object (because the bill usercontrol is built from
multiple controls & usercontrols). The only reel custom drawing I'm doingis
coming from my own built list (see $Test-LoadFactures-Opened.jpg), but I
think this usercontrol has been optimized & corrected so there shouldn't be
any problem coming from it (I reverified to be sure). Except this one, all
other controls are derived from Microsoft controls or directly Microsoft
controls.

Here are new numbers by removing some parts of the bill usercontrol :
Objects USER / Objects GDI
100/178=Main win loaded
149/194=Win Gestion des factures loaded
4522/1817=All bills loaded (156) (1st) (W/O pics --> 633 GDI) (W/O
Histories --> 1053 GDI) (W/O Histos + W/O Hidden part --> 196 GDI)
4616/3432=All bills loaded (156) (2st) (W/O pics --> 1103 GDI.. BUG) (W/O
Histos --> 1908 GDI) (W/O Histos + W/O Hidden part --> 196 GDI)
4710/5047=All bills loaded (156) (3rd) (W/O Histos --> 2763 GDI) (W/O
Histos + W/O Hidden part --> 196 GDI)
390/5042=Win Gestion des factures closed (W/O Histos --> 2755 GDI) (W/O
Histos + W/O Hidden part --> 188 GDI)

My pictures are coming from a DrawingManager I made which stores all images,
icons & cursors.

Thank you, Tom, for you help. This project is a bit complex, mostly due to
the fact that it has been transported from VB6, Files saving format to
VB.NET, SQL Server. Though, I didn't have this problem with VB6.

I was wondering too, is the use of string concatenation is a good praticeor
not ? Are the strings created on the fly are cleaned up after the method is
finished (hopely so) ?

"Tom Shelton" <[email protected]> a écrit dans le message de (e-mail address removed)...




- Show quoted text -

Boy Jonathan,

Without really looking through the code, it's really hard to pinpoint
your issue. GDI leaks are almost always the result of a resource not
being disposed of correctly. At this poing, I would have to say you
might want to just start removing functionality until your leak is
resloved. Then you will know where to look.

I suppose you can send me the snapshots, and I'll see if I see
anything there.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top