Long-running processes

This site shows how to handle the long-running processes in the UI.

Basically, it should be avoided to execute long-running processes in the UI. If it is still necessary, you have to ensure that these processes do not run on the UI-thread. This article illustrates the possibilities one has to deal with it.

Rule number one: Do not block the UI thread!

If you write code which will be used by any UI components. You must always take care that the code does not include calls that can take a long time

protected void someMethodInUI()
{
final String label = someBusinessObject.invokeVeryLongOperation();
someUiObject.setText( label );
}

The problem in the line 3 is: you don't know how much time takes this call. And so long as the call lasts, the UI thread is waiting. In other words: the UI hangs.

Best Practice

The best practice to avoid this issue is to run the long-running processes within an eclipse job:

RunnableWithProgress runnable = new RunnableWithProgressBaseImpl()
{
@Override
protected void doRunWithCoreException( IProgressMonitor progressMonitor ) throws CoreException, InterruptedException
{
invokeVeryLongOperation();
}
};
IProgressService progressService = PlatformUI.getWorkbench()
.getProgressService();
Job job = new RunnableWithProgressJob( jobName, runnable );
job.schedule();
progressService.showInDialog( shell, job );

Important is to schedule the job before showing it in a dialog via the progress service. In this case the progress service waits for a short duration before opening the progress dialog. Otherwise the dialog appears always, also if the operation lasts only few miliseconds.

The advantage of using jobs is the possibility to add a JobListener to the job to be notified when the job is done:

job.addJobChangeListener( new JobChangeAdapter()
{
@Override
public void done( IJobChangeEvent event )
{
// IMPORTANT: access the UI stuff only within the UI thread!!!
Display.getDefault()
.asyncExec( new Runnable()
{
@Override
public void run()
{
updateUI();
}
} );
}
} );

If you don't want to show the progress dialog, you can also use an other function of the progress service: showing a busy cursor while an operation is running:

RunnableWithProgress runnable = new RunnableWithProgressBaseImpl()
{
@Override
protected void doRunWithCoreException( IProgressMonitor progressMonitor ) throws CoreException, InterruptedException
{
invokeVeryLongOperation();
}
};
IProgressService progressService = PlatformUI.getWorkbench()
.getProgressService();
progressService.busyCursorWhile( new RunnableWithProgressWrapper( runnable ) );

Disadvantages of this method:

  • the user is forced to wait until the operation is finished

  • no listener registration is possible (e.g. to be notified when the operation is done)