DotNet Controls

This forum is meant for questions and discussions about the X# language and tools
ecos
Posts: 91
Joined: Tue Nov 10, 2015 6:49 am

DotNet Controls

Post 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
User avatar
Chris
Posts: 4562
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

DotNet Controls

Post 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.
Chris Pyrgas

XSharp Development Team test
chris(at)xsharp.eu
ecos
Posts: 91
Joined: Tue Nov 10, 2015 6:49 am

DotNet Controls

Post 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
User avatar
Chris
Posts: 4562
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

DotNet Controls

Post 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.
Chris Pyrgas

XSharp Development Team test
chris(at)xsharp.eu
User avatar
Chris
Posts: 4562
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

DotNet Controls

Post 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.
Chris Pyrgas

XSharp Development Team test
chris(at)xsharp.eu
ecos
Posts: 91
Joined: Tue Nov 10, 2015 6:49 am

DotNet Controls

Post 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
User avatar
Chris
Posts: 4562
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

DotNet Controls

Post 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?
Chris Pyrgas

XSharp Development Team test
chris(at)xsharp.eu
ecos
Posts: 91
Joined: Tue Nov 10, 2015 6:49 am

DotNet Controls

Post 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
Terry
Posts: 306
Joined: Wed Jan 03, 2018 11:58 am

DotNet Controls

Post by Terry »

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

 
ecos
Posts: 91
Joined: Tue Nov 10, 2015 6:49 am

DotNet Controls

Post 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
Post Reply