Page 1 of 2
DotNet Controls
Posted: Tue Aug 08, 2023 8:28 am
by ecos
Hi,
if I put e. g. a toolstrip on a VO-Dialogwindow with setparent(toolstrip:handle,oDlg:handle()), is it necessary to dispose() the toolstrip in the close-method of the dialogwindow ?
And if yes, do I also have to dispose the controls on the toolstrip like ToolStripButtons, ToolStripDropDownButtons, ToolStripMenuItems ?
TIA
Karl
DotNet Controls
Posted: Tue Aug 08, 2023 9:33 am
by Chris
Hi Karl,
I can't think of a reason to do this (well, except for to free the memory more quickly, but I doubt a toolstrip uses a lot of memory), since when the window gets destroyed and there are no references anymore to the toolstrip object, the GC will kick in and dispose it automatically.
DotNet Controls
Posted: Tue Aug 08, 2023 9:43 am
by ecos
Hi Chris,
that's what I hoped. I just was not sure what happens in winforms with "SELF:Controls:Add(...)". Could have been that they are somehow registered and released when the winform is closed. I didn't find any detailed explanation so far. So it should be safe to rely on the GC...
Thanks,
Karl
DotNet Controls
Posted: Tue Aug 08, 2023 3:20 pm
by Chris
Hi Karl,
Yes, indeed calling Controls:Add() registers all the controls in an internal array, which when you call Dispose() on a form, is used to Dispose() all its controls, too, you can actually see the code here:
https://source.dot.net/#System.Windows. ... ol.cs,5116
And when Close() is called to close a form, then actually it manually disposes the object (together with its contained controls, too):
https://source.dot.net/#System.Windows. ... rm.cs,3047
On the other hand, when a form is closed from the "X" button, I don't see it being disposed right then, although I might have missed it.
So now I'm not completely sure for my suggestion. To be sure, you can do something like that to monitor when the toolstrip does get disposed, define a class of yours:
CLASS MyToolStrip INHERIT System.Windows.Forms.ToolStrip
DESTRUCTOR()
System.Windows.Forms.MessageBox.Show( "Toolstrip Destructed" )
OVERRIDE PROTECTED METHOD Dispose(lDisposing AS LOGIC) AS VOID
SUPER:Dispose(lDisposing)
System.Windows.Forms.MessageBox.Show( "Toolstrip Disposed" )
END CLASS
and let your toolstrip inherit from that class. Then run your application normally and open/close windows that have the toolstrip. If the app runs for a long period of time (so the GC should had eventually kicked in and collect the toolstrip) but you do not get a window message that this has indeed happened (eventually it WILL happen when you shut down the app), then it means that indeed for all that time the control remained in memory, so it would be better to dispose it manually as soon as the window is closed.
DotNet Controls
Posted: Tue Aug 08, 2023 3:47 pm
by Chris
Hmm, I followed my own advice and added such a toolstrip (a lot actually) to a pure WinForms app, and they never seem to get disposed (before the app terminates), unless I manually dispose them (or the parent form)!! On the other hand, "regular" controls like CheckBox, TextBox etc do get soon disposed. I suspect this happens because the toolstrip does not have a Win32 underlying control with resources (as it is a new control to WinForms), it's just manually printed on screen by GDI code and it is very light weight. So, even though its footptint is probably very small and won't make much of a difference (unless you create thousands of toolstrips), it wouldn't hurt if you manually dispose them after all.
DotNet Controls
Posted: Wed Aug 09, 2023 6:02 am
by ecos
Hi Chris,
I think it's better to add an equivalent to controls:add to VO-Windows with winform-controls. I did some testing and the destructors and dispose-methods of my subclassed controls are never called, not even when the application terminates. I have dialogwindows with 30 chart-controls and disposing the controls manually immediately frees quite a lot of memory. I tested this with GC.GetTotalMemory(TRUE) before and after the dispose-calls of the controls.
So more work to be done...
Karl
DotNet Controls
Posted: Wed Aug 09, 2023 2:10 pm
by Chris
Hi Karl,
If they don't get called even when the app terminates, then there's some mistake in the code logic (or the app ends abruptly), those should ALWAYS be called at least at the end. Or it means that GC.SuppressFinalize() (by you or system code) has been called on those objects, to explicitly prevent calling their destructors.
The most basic functionality of Controls:Add() in winforms I think is not to dispose them later, but it's a more basic function, it's the only way to actually put a control in a form. Having a list of controls easily accessible is a bonus I guess. But in any case, I think it's a good idea to introduce some way to do that for winform controls in VO windows as you suggested. Maybe a method like
METHOD InsertWinFormsControl(oControl AS System.Windows.Forms.Control, oContainer AS VO.Control) AS VOID
which would put the winforms control inside the VO control you specify (with SetParent()), and also keep track of such controls added, to dispose them when the window closes.
Can you please log a feature request for that?
DotNet Controls
Posted: Thu Aug 10, 2023 7:59 am
by ecos
Hi Chris,
I'm a bit lost. My application terminates as expected but the destructors are never called. I did a test with my chart-control example (you have it) and there the destructors are called when the application terminates. They are also called after a gc.collect(), so there everything is fine. Could it be that a compiler-switch causes this ?
One thought:
So far I use these controls in external dll's which are loaded via xSharpLoadLibrary. Could this cause the missing call ?
I'll do some further testing...
Karl
DotNet Controls
Posted: Thu Aug 10, 2023 10:18 am
by TerryB1
PMFJI
It is always advisable for objects to be discarded as soon as possible. It saves time. Basically this is because all processing is routed through the processor and even the short time it takes (pico-seconds) to route things this way, when there are thousands of objects waste of time becomes significant.
This is all part of the underlying electronic processsing and I am 99.999% confident will have been taken into account in design/implementation of system software. Hence there will be no need for programmers to do it, in most cases, explicitly.
There is no way I can definitively answer the original question. Nor do I think there is any amount of experimentation that will do the trick.
Just to illustrate: in respect of controls and and on screen graphics, as a programmer you will always be first to know when your screen has been painted, it needs no repaint (unless there is a change in which case it must be re-generated anyway) simply because it remains in that state due to refresh rate of monitor. So graphical objects, pens and so on can, and should be, discarded immediately and explicitly.
Terry
DotNet Controls
Posted: Thu Aug 10, 2023 12:03 pm
by ecos
Hi Terry, Chris,
Terry,
I do agree that it's always a good idea to dispose objects as soon as possible. It is however quite calming that you can rely on the GC in a 24/7-application if something slipped through...
It seems that my application "eats" the messageboxes I inserted in the destructor of my chart-controls when the app terminates. If I insert
gc.Collect(1000,GCCollectionMode.Forced,TRUE)
after closing the dialogwindow, the messages pop up and the controls are disposed. So everything seems to be fine.
Chris, I'm not sure what you mean with
METHOD InsertWinFormsControl(oControl AS System.Windows.Forms.Control, oContainer AS VO.Control) AS VOID
I don't have a container-control, my attempt is:
Code: Select all
METHOD AddWinformControl(oCtrl AS System.Windows.Forms.Control) AS VOID //class MyDialogwindow (inherit Dialogwindow)
setparent(oCtrl:Handle,SELF:Handle())
AAdd(SELF:WFControls,oCtrl)
RETURN
METHOD Destroy()
LOCAL n AS DWORD
LOCAL oCtrl AS System.Windows.Forms.Control
SUPER:Destroy()
FOR n := 1 UPTO ALen(SELF:WFControls)
oCtrl := SELF:WFControls[n]
oCtrl:Dispose()
NEXT
RETURN SELF
Is anything wrong with this ?
Karl