Threading

Survey Core (and therefore the API) is a little unconventional in its use of threads and processing of events.  This is described in detail below.

Threading classes are available in SC version 1.90 onwards.  Monitors are available in all versions.

Event handling, waits, and threads

Under normal circumstances, a Survey Core thread will be in a wait state, awaiting events to be processed.  This wait is a function within Survey Core which waits for a variety of internal events (including Window messages) and calls the appropriate event handlers in the plugin as they occur.  Event handlers are always called on the same thread that requested the event, and this takes much of the pain out of the cross-thread signalling which would otherwise be required.  The SC wait functions are not visible (other than tsc_SurveyCore::Sleep()), and are called automatically.  The programmer implements only the necessary event handlers.

This event-handling process can operate correctly only when the thread uses the waits provided by the API; if any Windows API blocking call is used, such as Sleep() or WaitForSingleObject(), then control of the thread is lost and SCAPI will cease to generate events until the wait exits. This could result in slow or intermittent UI or even a deadlock of the entire application in some situations.

Event handlers are known as Monitors in SCAPI.  A monitor is an interface which can be subclassed, and some virtual event handling functions implemented.  A monitor may be used in any class, with the exception of instances called from a tsc_Thread. 

Trimble Access uses multi-threading to enable its concurrent workflow paradigm. This allows the user to, for instance, concurrently stake out a fence line, design a road, and browse a map of the area, without losing track of what stage each workflow is at.

tsc_UITask class

When handling a selection a user made from the main window of a plugin application (or launching a plugin task by any means), Survey Core creates a tsc_UITask (User-interface-task) instance and calls its Run method, which has been implemented by the plugin to process the selection.  A UI task typically runs on a separate thread which behaves similarly to a tsc_MonitorThread (see below).  In most situations, events may be generated and handled on this thread without starting other threads.  Occasionally a separate thread is required, and one of the thread classes described below may be used for this.

It is worth noting that Trimble Access forms and UI in general, is modeless between threads and therefore between UITasks. Within one thread (UITask) the UI becomes modal, in that one form may open a second form but the first form remains inaccessible until the second is closed. In other words, the user may only interact with the most recent (and therefore topmost) form in one UITask. Each UITask has its own stack of forms of which only the topmost is accessible. Furthermore, only one UITask is active at a time but the user may switch between any UITasks. The Map is a special case and can be interacted with at most times.

tsc_Thread class

If the plugin programmer wishes to use Windows API wait functions (or any other API which uses internal waits) then the tsc_Thread class may be used to make these safe while still allowing access to the Survey Core API.

A monitor class may not be used within a tsc_Thread, because tsc_Thread works with the Windows API wait model rather than Survey Core's event model.

tsc_MonitorThread class

If a thread is required that handles SC events using monitor classes, then tsc_MonitorThread must be used instead of tsc_Thread.  A thread created using tsc_MonitorThread operates similarly to a normal API thread running in a UI task.

It is useful to be able to send messages to and from a tsc_MonitorThread in an asynchronous fashion.  For this, use the tsc_Event and tsc_EventDelegate classes which implement a multicast event system.  Timer events may be obtained using the tsc_ITimerMonitor class.

tsc_QuickTask class

In addition to tsc_Thread and tsc_MonitorThread, a third type of thread is supplied by SCAPI, called tsc_QuickTask.  A quick task is a very lightweight thread object used to perform short non-waiting tasks, such as regularly flushing a buffer every few seconds.  Many internal "quick tasks" share a small number of common threads (a thread pool) along with the tsc_QuickTask.

Resource locking

When a resource (which could be anything from an integer or double to a complex structure) is possibly accessed by more than one thread, it is prudent to lock the resource while it is being changed or accessed.  The tsc_Lock macro provides the functionality to do this quite simply.

Also see