Salesforce

Hybrid objects assigned to System.Windows.Forms.Timer:Tag are never garbage collected

« Go Back

Information

 
TitleHybrid objects assigned to System.Windows.Forms.Timer:Tag are never garbage collected
URL NameHybrid-objects-assigned-to-System-Windows-Forms-Timer-Tag-are-never-garbage-collected
Article Number000126132
EnvironmentProduct: OpenEdge
Version: 11.7.3.x
OS: All supported platforms
Question/Problem Description
Hybrid objects assigned to System.Windows.Forms.Timer:Tag are never garbage collected

When assigning a hybrid object (ABL object inheriting from a .Net object) to the Tag property of a System.Windows.Forms.Timer and removing it again in the Timer:Tick event, the object never gets garbage collected.  For example the hybrid class is:
USING System.Object FROM ASSEMBLY.
BLOCK-LEVEL ON ERROR UNDO, THROW.

CLASS SimpleObject
    INHERITS Object:
END CLASS.

If this is assigned to a timer Tag property:
DEFINE PRIVATE VARIABLE Timer AS System.Windows.Forms.Timer NO-UNDO.
...
THIS-OBJECT:Timer = NEW System.Windows.Forms.Timer(THIS-OBJECT:components).
...
Timer:Tag = NEW SimpleObject().
Timer:Start().
The timer Tick event handler removes the reference to the hybrid class, so it should be garbage collected:
METHOD PRIVATE VOID Timer_Tick(sender AS Object, e AS EventArgs):
        Timer:Stop().
        ASSIGN Timer:Tag = ?.
END METHOD. /* Timer_Tick */

But this never happens.  With DynObjects.Class client logging it can be seen in the log that the object is never garbage collected:

[18/09/05@09:41:01.647+0100] P-019624 T-021376 2 4GL DYNOBJECTS     Created        Progress.Lang.Object    Handle:1024 (StartLeakingButton_Click TimerLeakForm @ 50) SimpleObject

There is never a corresponding Deleted line for this object in the log.  

 
Steps to Reproduce
Clarifying Information
If the hybrid object is replaced by a pure .Net object, the problem doesn't happen.  For example:
DEFINE PRIVATE VARIABLE Timer AS System.Windows.Forms.Timer NO-UNDO.
...
THIS-OBJECT:Timer = NEW System.Windows.Forms.Timer(THIS-OBJECT:components).
...
Timer:Tag = NEW System.Object().
Timer:Start().


 
Error Message
Defect Number
Enhancement Number
Cause
This is expected behavior. 
Resolution
The objects are being garbage collected, but this isn't happening immediately because .NET simply hasn't performed garbage collection yet.  In addition to this the OpenEdge client waits until .Net has completed garbage collection before it garbage collects the ABL side of the objects.  In this case when .Net does perform garbage collection the client log has already been closed.  If the code forces garbage collection in the Timer_Tick routine of TimerLeakForm:
 
System.GC:Collect().
System.GC:WaitForPendingFinalizers().
System.GC:Collect().

Then this will force the objects to be garbage collected and shows the ABL side of the objects being garbage collected in the client log:

[18/09/05@09:41:04.146+0100] P-019624 T-021376 2 4GL DYNOBJECTS     Deleted-by-GC  Progress.Lang.Object    Handle:1024 (StartLeakingButton_Click TimerLeakForm @ 0) SimpleObject

The fact that these objects appear to be left is something peculiar to hybrid objects and is explained in article  Objects not deleted from memory immediately.  It's not possible for the OpenEdge client to know when .Net will perform garbage collection and it shouldn't be necessary (and isn't recommended) to force it as described above. But Microsoft explain the algorithm they use at:

https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals
 
Workaround
Notes
Keyword Phrase
Last Modified Date11/20/2020 7:07 AM

Powered by