Click or drag to resize

Controller Events and Threads

Overview

A controller event is a message from the controller that something has happened. Events can be caught and acted upon by FlexPendant SDK applications.

Controller events use their own threads. This means that user interface threads and controller event threads can get into conflict. This section gives information on how to prevent this.

Controller events

FlexPendant SDK applications can subscribe to a number of controller events. These are all described in the Reference Manual FlexPendant SDK.

The table shows some events that exists in the FlexPendant SDK.

The event...

occurs when...

StateChanged

the controller state has changed.

OperatingModeChanged

the controller operating mode has changed.

ExecutionStatusChanged

the controller execution status has changed.

Changed

the value or the state of the I/O signal has changed.

MessageWritten

the EventLog has a new message

ValueChanged

the value of a RAPID data has changed.

Note Note

There is no guarantee you will get an initial event when setting up/activating a controller event. You need to read the initial state from the controller.

GUI and controller event threads in conflict

You should be aware that controller events use their own threads both on the FlexPendant and PC platform. If a GUI thread and a controller event thread get into conflict, deadlocks or overwritten data may occur. This may happen when a controller event is succeeded by an update of the user interface, which is indeed a very common scenario.

You then need to take action in your code to control that the user interface update is executed by the GUI thread and not by the controller event thread. This is done by enforcing a thread switch using the Invoke or BeginInvoke method. For more information on how this is done along with code examples, see Invoke method.

On the other hand, if the controller event should NOT cause any update of the user interface, you should not take any special action. Using Invoke or BeginInvoke is performance demanding and should not be used more than necessary.

Note Note

Thread conflicts often cause hangings. The FlexPendant touch screen then stops responding and the application has to be restarted. Examine what exception has been thrown when you encounter such a situation. The exceptions System.NotSupportedException (FlexPendant platform) and System.InvalidOperationException (PC platform) indicate thread conflicts. See the next section for information on how to use Invoke to solve the problem.

Invoke method

All FlexPendant views must inherit Control / TpsControl, which implement Invoke and BeginInvoke. These methods execute the specified delegate/event handler on the thread that owns the control's underlying window handle, thus enforcing a switch from a worker thread to the GUI thread. This is precisely what is needed when a controller event needs to be communicated to the end user of the system.

Invoke should be called inside the event handler taking care of the controller event. Notice that you have to create a new object array for the sender and argument objects:

C#
this.Invoke(new EventHandler(UpdateUI), new Object[] {sender, e});
VB
Me.Invoke(New EventHandler(AddressOf UpdateUI), New Object() {sender, e})

Also notice that if you use EventHandler in the Invoke method and not the specific delegate class, for example DataValueChangedEventHandler, you need to typecast the argument in the delegate which updates the user interface. How this is done is shown in the following example:

C#
private void UpdateUI(object sender, System.EventArgs e)

{

ExecutionStatusChangedEventArgs args;

args = (ExecutionStatusChangedEventArgs) e;

this.label1.Text = e.NewStatus.ToString();

}
VB
Private Sub UpdateUI(ByVal sender As Object, ByVal e As System.EventArgs)

Dim Args As ExecutionStatusChangedEventArgs

Args = DirectCast(e, ExecutionStatusChangedEventArgs)

Me.Label1.Text = e.NewStatus.ToString()

End Sub
Note Note
The difference between Invoke and BeginInvoke is that the former makes a synchronous call and will hang until the GUI operation is completed, whereas BeginInvoke executes the specified event handler asynchronously. Which method you want to use depends on the logics of your program. The recommendation is to choose BeginInvoke whenever possible.
Note Note
If your code tries to access a GUI control from a background thread the .NET common language runtime will throw a System.NotSupportedException (FlexPendant platform) or a System.InvalidOperationException (PC platform).
Tip Tip
If you are using the FlexPendant SDK there is further information about threads in Reliability.