If the command takes a long time to execute, the user interface will be blocked. This happens because there is only one user interface thread, and because the command is launched from the UI, it will run in the UI thread. Instead, long-running operations should run in a background thread, and then once finished, be able to display the results. Clearly creating a new Thread
(like the clock updates initially) or other techniques such as a Timer
would work. However, the Eclipse system has a mechanism to provide a Job
to do the work instead, or UIJob
to run in the context of the UI thread.
HelloHandler
and go to the execute
method. Replace its contents with the following:public void execute() { Job job = new Job("About to say hello") { protected IStatus run(IProgressMonitor monitor) { try { Thread.sleep(5000); } catch (InterruptedException e) { } MessageDialog.openInformation(null, "Hello", "World"); return Status.OK_STATUS; } }; job.schedule(); return; }
activeContexts
in the plugin.xml
to allow the command to be shown in the org.eclipse.ui.contexts.dialogAndWindow
context). Open the Progress view, and a Job
will be listed with About to say hello running. Unfortunately, an error dialog will then be shown:Job
runs on a non-UI background thread, so when the MessageDialog
is shown, an exception occurs. To fix this, instead of showing the MessageDialog
directly, a second Job
or Runnable
can be created to run specifically on the UI thread. Replace the call to the MessageDialog
with:public void execute(final UISynchronize display) { ... // MessageDialog.openInformation(null, "Hello", "World"); display.asyncExec(() -> { MessageDialog.openInformation(null, "Hello", "World"); });
This example uses the asyncExec
method to run a Runnable
on the UI thread (similar to SwingUtilities.invokeLater
method in Swing).
Every modification to the Eclipse UI must run on the UI thread; so if the command takes a significant time to run and is running on the UI thread, it will give the impression that the user interface is blocked. The way to avoid this is to drop out of the UI thread before doing any long-term work. Any updates that need to be done involving the UI should be rescheduled back on the UI thread.
The example used both the Job
API (a mechanism for scheduling named processes that can be monitored via the progress view) as well as the UISynchronize
method asyncExec
to launch the resulting message dialog.
Instead of scheduling the UI notification piece as a display.asyncExec
, create it as a UIJob
. This works in exactly the same way as a Job
does, but it is necessary to override the runInUIThread
method instead of the run
method. This may be useful when there is more UI interaction required, such as asking the user for more information.
3.144.33.41