Este tutorial trata sobre eclipse Job y consta de dos partes. La primera parte presenta cómo hacer una barra de progreso usando un ejemplo simple. La segunda parte ilustra brevemente el trabajo de Eclipse para el procesamiento en segundo plano.
1. Un ejemplo simple de barra de progreso en Eclipse
Suponga que tiene una aplicación RCP en funcionamiento con un menú «Hola mundo» de muestra y la acción correspondiente. (Esto se puede hacer en poco tiempo utilizando el asistente de extensión de eclipse)
Para informar el progreso de alguna tarea ejecutable, se requieren las siguientes clases:
1. org.eclipse.core.runtime.jobs.Job
(Los trabajos son unidades de trabajo ejecutables que se pueden programar para que se ejecuten con el administrador de trabajos. Una vez que se ha completado un trabajo, se puede programar para que se ejecute nuevamente)
2. org.eclipse.core.runtime.IProgressMonitor
Para tener una idea de cómo se ve una barra de progreso, simplemente reemplace el método de ejecución con el siguiente código. No hace un trabajo real, solo imita una tarea real.
public void run(IAction action) { Job job = new Job("Test Job") { @Override protected IStatus run(IProgressMonitor monitor) { // Set total number of work units monitor.beginTask("start task", 100); for (int i = 0; i < 10; i++) { try { Thread.sleep(1000); monitor.subTask("doing " + i); // Report that 10 units are done monitor.worked(10); } catch (InterruptedException e1) { e1.printStackTrace(); } } return Status.OK_STATUS; } }; job.schedule(); } |
Agregue la siguiente declaración al método preWindowOpen de la clase ApplicationWorkbenchWindowAdvisor.
public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor { public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) { super(configurer); } public ActionBarAdvisor createActionBarAdvisor( IActionBarConfigurer configurer) { return new ApplicationActionBarAdvisor(configurer); } public void preWindowOpen() { IWorkbenchWindowConfigurer configurer = getWindowConfigurer(); configurer.setInitialSize(new Point(400, 300)); configurer.setShowCoolBar(false); configurer.setShowStatusLine(false); configurer.setTitle("RCP Application"); configurer.setShowProgressIndicator(true); } } |
2. Habilitar el procesamiento en segundo plano
Suponga que tiene una aplicación cliente enriquecida con una vista y un botón. Cuando se hace clic en el botón, se inicia un trabajo que requiere mucho tiempo.
Si este costoso trabajo se implementa de una manera sencilla, es decir, se implementa en el hilo principal, la vista de la aplicación no responderá. Si hace clic en otro menú o botón, nadie responderá. Esto podría ser molesto para muchos usuarios y hacerles creer que necesitan terminar el proceso.
public void createPartControl(Composite parent) { Composite top = new Composite(parent, SWT.NONE); // setup the layout of top to be GridLayout. GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; top.setLayout(layout); Button button = new Button(top, SWT.PUSH); button.setText("test button"); Listener listener = new Listener() { public void handleEvent(Event event) { //expensive job below for (int i = 0; i < 10; i++) { try { Thread.sleep(2000); System.out.println(i); } catch (InterruptedException e) { e.printStackTrace(); } } } }; button.addListener(SWT.Selection, listener); } |
Una posible solución es crear varios subprocesos y luego sincronizarlos entre sí. Esto debería funcionar, pero la plataforma Eclipse proporciona una forma sencilla.
Con Eclipse, podemos dedicar mucho tiempo a un trabajo. La clase Job, que se proporciona en el complemento org.eclipse.core.runtime, permite a los clientes ejecutar fácilmente el código en un subproceso separado. Además, se puede agregar fácilmente una barra de control de progreso.
Listener listener = new Listener() { public void handleEvent(Event event) { Job job = new Job("test") { @Override protected IStatus run(IProgressMonitor monitor) { monitor.beginTask("start task", 100); //time consuming work here doExpensiveWork(monitor); //sync with UI syncWithUI(); return Status.OK_STATUS; } }; job.setUser(true); job.schedule(); } }; |
doExpensiveWork y syncWithUI se definen de la siguiente manera:
private void doExpensiveWork(IProgressMonitor monitor) { // mimic a long time job here for (int i = 0; i < 10; i++) { try { //give a progress bar to indicate progress monitor.worked(10); Thread.sleep(2000); System.out.println("step: " + i); } catch (InterruptedException e) { e.printStackTrace(); } } } private void syncWithUI() { Display.getDefault().asyncExec(new Runnable() { public void run() { MessageDialog.openInformation(getSite().getShell(), "message", "completed!"); } }); } |
asyncExec permite que el hilo de llamada sea asincrónico con el hilo de llamada. El autor de la llamada de este método continúa ejecutándose en paralelo y no se le notifica cuando se completa el ejecutable.
En su lugar, podemos usar syncExec, en cuyo caso el hilo que llama a este método se suspende hasta que se completa el ejecutable.
La diferencia es evidente en esta demostración. syncExec tiene que esperar que el usuario haga clic en el botón «Aceptar» para completar, mientras que asyncExec no lo hace.
Referencia