Sunday, January 10, 2010

Updating UI in Eclipse RCP

Introduction:

In Eclipse RCP, generally the code is executed in UI thread most of the time. Running long operations here would freeze UI. I've blogged about this in my previous post. So, the solution is to either spawn off a separate thread or if you want to show progress to the user, use Jobs API as illustrated in point 5 in previous post and execute long running operation there. But, if you want to update UI while the code is running in non-UI thread, you need to make sure that it is done via UI thread. Otherwise, you will get bizzare behavior during runtime.

Swing:

If you are a Swing programmer, you are already familiar with this concept. In Swing, generally the code is run in event dispatch thread and all UI update operations need to be done from this thread. If you want to update UI while running long operations in another thread, you need to use SwingUtilities.invokeLater or SwingUtilities.invokeAndWait for this purpose. You can read more about it from this post.

Eclipse RCP:

In Eclipse, the idea is similar. All UI update operations need to be done from UI thread. So, if you want to update UI from other threads, you need to use Display.asyncExec or Display.syncExec method.

Display.getDefault().asyncExec(new Runnable() {
public void run() {
// Update UI here
}
});
System.out.println("This could be printed before run method finishes...");

Display.asyncExec would execute the run() method asynchronously (similar to invokeLater) i.e the thread which calls executes asyncExec line would get executed in parallel with the run() method.

Display.getDefault().syncExec(new Runnable() {
public void run() {
// Update UI here
}
});
System.out.println("This would be printed after run method finishes...");

Display.syncExec follows similar syntax and would execute the run() method synchronously (similar to invokeAndWait) i.e the thread which calls executes syncExec line would get executed wait until run() method finishes.

In general, it is good to use asyncExec, unless you specifically want the calling thread to block.