Threading issues

When working with a widget toolkit, it is important to understand the underlying thread model that is used for reading and dispatching platform GUI events. The implementation of the UI thread affects the rules that applications must follow when using Java threads in their code.

Native event dispatching

Underneath any GUI application, regardless of its language or UI toolkit, the OS platform detects GUI events and places them in application event queues. Although the mechanics are slightly different on different OS platforms, the basics are similar. As the user clicks the mouse, types characters, or surfaces windows, the OS generates application GUI events, such as mouse clicks, keystrokes, or window paint events. It determines which window and application should receive each event and places it in the application's event queue.

The underlying structure for any windowed GUI application is an event loop. Applications initialize and then start a loop which simply reads the GUI events from the queue and reacts accordingly. Any work that is done while handling one of these events must happen quickly in order to keep the GUI system responsive to the user.

Long operations triggered by UI events should be performed in a separate thread in order to allow the event loop thread to return quickly and fetch the next event from the application's queue. However, access to the widgets and platform API from other threads must be controlled with explicit locking and serialization. An application that fails to follow the rules can cause an OS call to fail, or worse, lock up the entire GUI system.

SWT UI thread

SWT follows the threading model supported directly by the platforms. The application program runs the event loop in its main thread and dispatches events directly from this thread. The UI thread is the thread in which the Display was created. All other widgets must be created in the UI thread.

Since all event code is triggered from the application's UI thread, application code that handles events can freely access the widgets and make graphics calls without any special techniques. However, the application is responsible for forking computational threads when performing long operations in response to an event.

Note: SWT will trigger an SWTException for any calls made from a non-UI thread that must be made from the UI thread.

The main thread, including the event loop, for an SWT application has the following structure:

   public static void main (String [] args) {
      Display display = new Display ();
      Shell shell = new Shell (display);
      shell.open ();
      // start the event loop. We stop when the user has done
      // something to dispose our window.
      while (!shell.isDisposed ()) {
         if (!display.readAndDispatch ())
            display.sleep ();
      }
      display.dispose ();
   }

Once the widgets are created and the shell is opened, the application reads and dispatches events from the OS queue until the shell window is disposed. If there are no events available for us in the queue, we tell the display to sleep to give other applications a chance to run.

SWT provides special access methods for calling widget and graphics code from a background thread.

Executing code from a non-UI thread

Applications that wish to call UI code from a non-UI thread must provide a Runnable that calls the UI code. The methods syncExec(Runnable) and asyncExec(Runnable) in the Display class are used to execute these runnables in the UI thread during the event loop.

The following code snippet demonstrates the pattern for using these methods:

   // do time-intensive computations
   ...
   // now update the UI. We don't depend on the result,
   // so use async.
   display.asyncExec (new Runnable () {
      public void run () {
         if (!myWindow.isDisposed())
            myWindow.redraw ();
      }
   });
   // now do more computations
   ...

It is good practice to check if your widget is disposed from within the runnable when using asyncExec. Since other things can happen in the UI thread between the call to asyncExec and the execution of your runnable, you can never be sure what state your widgets are in by the time your runnable executes.

The workbench and threads

The threading rules are very clear when you are implementing an SWT application from the ground up since you control the creation of the event loop and the decision to fork computational threads in your application.

Things get a bit more complicated when you are contributing plug-in code to the workbench. The following rules can be considered "rules of engagement" when using platform UI classes, although from release to release there may be exceptions to these rules: