Click or drag to resize

GUI controls and memory management

Overview

All of the FlexPendant SDK controls belong to the ABB.Robotics.Tps.Windows.Forms namespace. This namespace thus includes well over 40 classes and subclasses used to develop the user interface of a FlexPendant application.

ABB.Robotics.Tps.Windows.Forms.TpsControl is the base type of all FlexPendant SDK controls. TpsControl in turn extends System.Windows.Forms.UserControl

TpsControl may be used as a container control of a FlexPendant view. It also has the default implementation of Dispose , which is called in order to free allocated memory for a control which should no longer be used.

You may wonder why this is necessary, as the .NET framework has a garbage collector, which should release the developer of the duty to free allocated memory. The answer is the garbage collector does not always reclaim memory which is no longer used. Therefore, if you program an application meant to execute around the clock on a device with limited memory, you are still responsible for freeing memory which is no longer used. Neglecting to do so will result in permanent memory leaks.

How to avoid memory leaks

Look at this figure showing a number of controls (both ABB and Microsoft) and learn the basics about memory management for GUI controls. It is not so complicated, the most important thing is not to forget that cleaning up is your responsibility!

6.3.2 1 Controls And Mem Leak

Learn and apply these the general rules for memory management of GUI controls.

  • Controls with a graphical representation, e.g the ABB Numpad,TabControl, GroupBox, TpsLabel, ListView and the Microsoft PicureBox and Datagrid in the figure are automatically added to the controls collection in InitializeComponent. It may look like this: this.Controls.Add(this.numPad1);.

  • If the preceding figure represents the first view of your application, controls with graphical representation will be disposed of by the base class of your view class when your application is shut down and the Dispose method is called by TAF. This happens when the following statement in your method is executed: base.Dispose(disposing);

  • If, however, it represents a secondary view of your application (which is actually the case here, as you can tell from the close button on the command bar), you must call its Dispose method from the first view when it is closed. Its base class will then remove all controls that are part of its controls collection, like in the previous case.

  • GUI controls that have no graphical representation, but are located in the Components pane under the form, for example GTPUSaveFileDialog, RapidDataBindingSource, AlphaPad and so on are NOT added to the controls collection by default. These are the ones that you need to be especially careful to remove, as no garbage collector will ever gather them. If you forget to explicitly call Dispose on such controls you will have caused a permanent memory leak. Carefully study the code example in the next section.

Note Note

Microsoft and ABB controls behave in the same way. The Microsoft ImageList for example, which is commonly used in FlexPendant applications, has no graphical representation and must thus be explicitly removed by the application programmer.

Coding the Dispose method

The following code example shows how the Dispose method of the view shown in the preceding figure can be coded. All controls located in the components pane in the Designer must be explicitly removed by the programmer. Controls with a graphical representation will be removed when Dispose of the base class is executed.

C#
protected override void Dispose(bool disposing)
{
if (!IsDisposed)
{
try
{
if (disposing)
{
//Removes SaveFile dialog
if(this.gtpuSaveFileDialog1 != null)
{
this.gtpuSaveFileDialog1.Dispose();
this.gtpuSaveFileDialog1 = null;
}
//Removes RapidDataBindingSource
if(this.rapidDataBindingSource1 != null)
{
this.rapidDataBindingSource1.Dispose();
this.rapidDataBindingSource1 = null
}
//Removes Alphapad
if(this.alphaPad1 != null)
{
this.alphaPad1.Dispose();
this.alphaPad1 = null
}
//Removes FolderBrowserDialog
if(this.gtpuFolderBrowserDialog1 != null)
{
this.gtpuFolderBrowserDialog1.Dispose();
this.gtpuFolderBrowserDialog1 = null
}
//Removes ImageList
if(this.imageList1 != null)
{
this.imageList1.Dispose();
this.imageList1 = null
}
}
}
finally
{
//Removes all controls added to the controls collection
base.Dispose(disposing);
}
}
}

Finally, as this is a secondary view, we should call its Dispose method from the first view when it is closed down.

C#
            //This code is executed by the first view when the secondary view is closed
            void form2_Closed(object sender, EventArgs e)
{
            if(form2 != null)
            {
            form2.Dispose();
            form2 = null;
            }
            }
Caution note Caution

If you forget to call Dispose on controls that are not part of the control collection of the class there will be memory leaks. This may cause the FlexPendant to run completely out of memory and crash. Usually, this will not happen when you try out the functionality of your application, but when it is executed and used continuously during production. To verify that a GUI control is really disposed of, you may set up a subscription to its Disposed event for example, and verify that it is triggered when you close down the view.

Caution note Caution

All objects accessing robot controller services, that is, unmanaged resources, must also be removed by the application programmer. For more information, see Memory management.

Freeing allocated memory for a GUI control

You are recommended to remove a GUI control in the Dispose method of the class that created it. If the control belongs to the first view of your application, it will be disposed of when TAF calls Dispose at application shut down. If it belongs to a secondary view, you are responsible for disposing of the secondary view and its controls.

C#
if (this.controlX != null)
{
controlX.Dispose();
controlX = null;
}
base.Dispose(disposing);
VB
If disposing Then
 If Not controlX Is Nothing Then
 controlX.Dispose()
 controlX = Nothing
 End If
 End If
 MyBase.Dispose(disposing)
Note Note

When the last statement in the preceding code example is executed the base class will call Dispose on all controls added to the controls collection in InitializeComponent. This means that you do not need to call Dispose on such controls.