When having a big monitor and a table representation with many column field colors, the BBrowser creates many objects that need GUI-Handles. These are mainly brushes. When the Garbage Collector cannot destroy these objects quickly, the maximum number of GUI-Handles per Windows process (normally 10000) can be reached and give "Create ressource and other GUI Errors).
In VO we regularly verified the number of GUI Handles and called the Garbage Collector explicitly when reaching 80% of the maximum. In X# we tried to do without. The GC in Dotnet is much quicker than the VO GC, but it seems that also here we can reach the limits.
What do you think is the best method:
- Try to change all occurrences in the BBrowser and try to destroy the objects explicitly where assigned temporarily?
- Try to re-use brush-objects in the BBrowser instead of creating new ones?
- Make a similar control as we made in VO?
- Something else?
Thanks
Arne
Bbrowser and reaching 10000 GUI-Handles
- ArneOrtlinghaus
- Posts: 413
- Joined: Tue Nov 10, 2015 7:48 am
- Location: Italy
Bbrowser and reaching 10000 GUI-Handles
Arne,
Are these all "unique" brushes, or many copies of the same brush?
Would it be an idea to cache the brushes that are retrieved with CreateSolidBrush() ?
How many colors are you really using in your bBrowsers? I doubt that there are more than 10.
Robert
Are these all "unique" brushes, or many copies of the same brush?
Would it be an idea to cache the brushes that are retrieved with CreateSolidBrush() ?
How many colors are you really using in your bBrowsers? I doubt that there are more than 10.
Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
The Netherlands
robert@xsharp.eu
- ArneOrtlinghaus
- Posts: 413
- Joined: Tue Nov 10, 2015 7:48 am
- Location: Italy
Bbrowser and reaching 10000 GUI-Handles
Robert,
it is as you say: Many objects with few different colors and normally hatchstyle = SOLID.
I did never think what CreateSolidBrush does. Do you mean that instead of creating a new brushobject I use Createsolidbrush to get a handle to a brush? In this case I should pay attention that the destroy method does not destroy/delete the brush.
it is as you say: Many objects with few different colors and normally hatchstyle = SOLID.
I did never think what CreateSolidBrush does. Do you mean that instead of creating a new brushobject I use Createsolidbrush to get a handle to a brush? In this case I should pay attention that the destroy method does not destroy/delete the brush.
Bbrowser and reaching 10000 GUI-Handles
Hi Arne,
How many different colors is many? I can't imagine in any case you have more than 100 different ones? In which case reusing instead of recreating sounds logical.
How many different colors is many? I can't imagine in any case you have more than 100 different ones? In which case reusing instead of recreating sounds logical.
Chris Pyrgas
XSharp Development Team
chris(at)xsharp.eu
XSharp Development Team
chris(at)xsharp.eu
- ArneOrtlinghaus
- Posts: 413
- Joined: Tue Nov 10, 2015 7:48 am
- Location: Italy
Bbrowser and reaching 10000 GUI-Handles
When looking at the code more exactly, I discovered only one place where a brush is generated directly. In the other cases always system brushes are used. I will change the occurrence and then I will look more carefully, which GUI objects are generated in such a big quantity.
- ArneOrtlinghaus
- Posts: 413
- Joined: Tue Nov 10, 2015 7:48 am
- Location: Italy
Bbrowser and reaching 10000 GUI-Handles
I have found some other places where a simple brush is created instead of reusing brushes - code that I have written many years ago. Finally I understand the consequences :woohoo: I will change all these places and measure the GUI Handle generation.
By the way: I use always the Process Explorer to verify or exclude strange effects: Dlls loaded, virtual memory, GUI Handles, Reads/Writes, Thread stack. It is such an important tool for me.
Another important tool is the resource monitor of Windows that can be reached via the Task Manager under "Performance". Looking the disk activity sometimes shows better what happens than looking at CPU consumation.
By the way: I use always the Process Explorer to verify or exclude strange effects: Dlls loaded, virtual memory, GUI Handles, Reads/Writes, Thread stack. It is such an important tool for me.
Another important tool is the resource monitor of Windows that can be reached via the Task Manager under "Performance". Looking the disk activity sometimes shows better what happens than looking at CPU consumation.
- ArneOrtlinghaus
- Posts: 413
- Joined: Tue Nov 10, 2015 7:48 am
- Location: Italy
Bbrowser and reaching 10000 GUI-Handles
It should be resolved now. I have made a function that buffers brushes in dependence of the color. Then I have substituted all occurences of creations of Brush{}-Objects and CreateSolidBrush-Calls, that did not use predefined Brushobjects from Windows.
So the generation of brushes in general is not the problem. But if the brush object is not destroyed in code in a tabular display the generation of objects can be so high that the Garbage Collector does not destroy them in time, because the GC does not see the need to go on more quickly - or has bigger objects to destroy.
We had similar effects with SQL Cursors that were not destroyed by program. In test situations everything went fine and then in the production environment "Maximum open cursors exceeded" messages happened because of more calls in short time.
function GetsolidBrushfromrgb(nrgb as dword) as brush
local npos as dword
local oColor as color
local obrush as object
if sabrushes == null_array
sabrushes := {}
endif
npos := ascandword (sabrushes, nrgb, 1)
if npos == 0
if alen(sabrushes) > 500
AAus (sabrushes, 1)
endif
oColor := Color {GetRValue(nrgb),GetGValue(nrgb),GetBValue(nrgb)}
obrush := brush{ocolor}
AAdd (sabrushes, {nrgb, obrush})
else
obrush := sabrushes[npos,2]
endif
return obrush
So the generation of brushes in general is not the problem. But if the brush object is not destroyed in code in a tabular display the generation of objects can be so high that the Garbage Collector does not destroy them in time, because the GC does not see the need to go on more quickly - or has bigger objects to destroy.
We had similar effects with SQL Cursors that were not destroyed by program. In test situations everything went fine and then in the production environment "Maximum open cursors exceeded" messages happened because of more calls in short time.
function GetsolidBrushfromrgb(nrgb as dword) as brush
local npos as dword
local oColor as color
local obrush as object
if sabrushes == null_array
sabrushes := {}
endif
npos := ascandword (sabrushes, nrgb, 1)
if npos == 0
if alen(sabrushes) > 500
AAus (sabrushes, 1)
endif
oColor := Color {GetRValue(nrgb),GetGValue(nrgb),GetBValue(nrgb)}
obrush := brush{ocolor}
AAdd (sabrushes, {nrgb, obrush})
else
obrush := sabrushes[npos,2]
endif
return obrush