Starting adapters and multithreading
This article discusses how to start an adapter and multithreading. Although these seem like separate issues, how you start your application affects how it works with events.
A Pega Robot Studio adapter is a class that is generated by the Studio tools. It encapsulates the data in an application and permits your code to monitor and modify how the application works.
Starting an adapter from .NET
There are a few ways to start an adapter from a .NET project. The simplest way is to use the adapter’s Start() method.
The Start() method can also take a parameter that provides a synchronization object. This object must implement the ISynchronizeInvoke interface. In practical terms, you pass it a Windows form UI object, such as a form or a control. Doing this lets the adapters automatically marshal their events to your UI, so you do not have to. This is because in Windows, you cannot modify a UI element safely except from the thread that the UI element was created on.
You only need to do this for adapters that you handle events from and that the event handlers modify UI items. If either of those conditions are not true, then you do not need to pass an object to the Start() method.
Crm.Start( <strong>this </strong>); // <strong><em>this</em></strong> is a System.Windows.Forms.Form object
Multithreading with adapters and .NET
If you start your application adapter with the Start() method and no synchronization, you need to handle marshalling events explicitly. This has the advantage of giving your code more control over how it is done, with the disadvantage of having to remember to do this or else exceptions might be thrown while your application is running.
Microsoft Windows, as a part of how Win32 works, requires that all changes made to a user interface control be done by the thread that created the control. It is, however, something that you need to be aware of, because it happens when handling events from external application adapters.
Studio adapters fire their events on different threads than your .NET application's UI thread. This keeps your application’s UI responsive, however, it also means that you need to marshal events to the UI thread to work with controls such as text boxes and labels. If you do not do this, you get cross-threading exceptions.
Advantages and disadvantages to each method
Start( this )
The advantages to using this method are that it is easy and safe and you do not need to worry about when you need to marshal code. Usually, you have a System.Windows.Forms.Form object that you can pass to the Start() method as a this object, which then correctly marshals all events for you.
The disadvantage to this method is that when your code is in an event handler, it is on the thread of the UI object and the UI object does not handle any repaint or other events until your code is done. This is only an issue if your code takes a long time to complete. This is no different from the usual event handlers in .NET code. In the cases where it does take a long time, you can place calls to the Update() method in your code to force a repaint or call the message loop, the Application.DoEvents() method, or you can spin off a different thread to handle the processing. Normally though, this is not an issue.
One thing to note is that all control events are marshaled for you. However, at this time, adapter events (Starting, Stopping, Stopped) are not marshaled and you still need to use the Invoke() method if you use these events and modify a UI while handling the event.
You have more control with this method of starting an adapter, but you must use the Invoke() method to marshal UI references to the correct thread.
The advantage of this method is that you have more control. The disadvantage of this method is that you need to be more careful when coding and debugging. Also, the same problem of long running events can still happen if you marshal the code to the UI thread and then take a long time in that thread.
How to marshal events in your code
The following is a sample pattern for handling an UI control safely from different threads. There are many patterns you can use; this one is self-contained. You can find out more by searching the Microsoft Developer Network (MSDN).
The important thing is to use the Invoke() method when updating anything on a UI control. Some examples are changing Text, clearing a list box, or working with a DataGridView. If you use the Invoke() method, you need to use a delegate.
The following example shows a delegate for passing a single string argument.
/// Handles updating the application bar's values. It’s done here so we can ensure its
/// thread safe for calls from the OpenSpan adapter.
/// account number for the window we are working with
public void handleToolbarUpdate( string keyText )
if ( InvokeRequired )
// Call self but on the correct thread
Invoke( new updateUI( handleToolbarUpdate ), keyText );
… the rest of your code …
If, however, you do not need to pass arguments, then you can use the MethodInvoker delegate, which is part of .NET. For example:
Invoke( new <strong>MethodInvoker</strong>( updateLabels ) );