Cómo ejecutar trabajos en el UI thread

Cuando estoy desarrollando plug-ins, de vez en cuando me sucede que necesito hacer algo tan simple como mostrar un diálogo y suelo caer casi siempre en el mismo error. Supongamos el siguiente ejemplo:

MessageBox mb = new MessageBox(plugin.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.OK);
mb.setMessage(message);
mb.setText("Launching...");
mb.open();

Este código lo tengo en un plug-in que contribuye a la interfaz de usuario. Cuando lo ejecuto, obtengo NullPointerException. Al depurar, veo que getActiveWorkbenchWindow devuelve null. La documentación de este método especifica:

Returns null if called from a non-UI thread.

El problema es que no puedo ejecutar este método si no estoy en el UI thread. Si depuramos la ejecución podemos ver que no se está ejecutando en el hilo de despacho de eventos:

non-UI_thread

Para ejecutar código que necesita acceder a la UI (como mostrar un cuadro de diálogo) tenemos dos alternativas: Display.asyncExec(Runnable) y UIJob. La primera ejecuta un objeto Runnable en el hilo de eventos en cuanto tenga una oportunidad. No es bloqueante y no se avisa al que invoca asyncExec cuando la tarea termina.

UIJob es más versátil, permite utilizar prioridades para definir la prioridad de las diferentes tareas, permite avisar al que especificó la tarea (mediante UIJob.addJobChangeListeners) y se pueden especificar políticas de planificación en caso de que esta tarea no pueda ejecutarse concurrentemente con tareas en otros hilos.

La forma de utilizar UIJob es simplemente crear un objeto, implementar el método runInUIThread(IProgressMonitor) y finalmente invocar el método UIJob.schedule() para dejar la tarea encolada en el hilo de despacho de eventos:

UIJob uijob = new UIJob("Launching...") {
  @Override
  public IStatus runInUIThread(IProgressMonitor monitor) {
    MessageBox mb = new MessageBox(plugin.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.OK);
    mb.setMessage(message);
    mb.setText("Launching...");
    mb.open();
    return Status.OK_STATUS;
  }
};
uijob.schedule();

Ahora nuestra tarea se ejecuta en el hilo adecuado (Main es el hilo de despacho de eventos):

UI_thread

 

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s