Supporto di simultaneità del workbench

È stato illustrato come il framework dell'UI JFace fornisca il supporto di base per la visualizzazione dell'avanzamento delle attività in una finestra di dialogo (per i dettagli, fare riferimento alla sezione Operazioni di lunga durata. Nella sezione Infrastruttura di simultaneità, è stato esaminato il supporto runtime della piattaforma per operazioni simultanee e di lunga durata. Viene ora esaminato come l'UI della piattaforma migliori questa infrastruttura nel pacchetto org.eclipse.ui.progress. Questo pacchetto fornisce l'UI per la visualizzazione dell'avanzamento del lavoro nel workbench e definisce un supporto supplementare per i lavori che vengono eseguiti nel thread UI.

Prima di introdurre le nuove API, è necessario rivedere alcuni argomenti. È necessario prima distinguere tra diversi tipi di operazioni di sfondo:


Dato un ambiente in cui possono accadere varie cose nello stesso tempo, l'utente ha bisogno dei seguenti elementi:

Vengono ora esaminati i dettagli ed il modo in cui possono essere utilizzate le nuove API.

Servizio di avanzamento

Il servizio di avanzamento del workbench (IProgressService) è l'interfaccia principale del supporto di avanzamento del workbench. Può essere richiamato dal workbench e utilizzato per mostrare l'avanzamento per le operazioni di sfondo e le operazioni che vengono eseguite nel thread dell'UI. Lo scopo principale di questa classe è fornire la possibilità di scegliere rapidamente le operazioni in esecuzione, facendo in modo che gli sviluppatori di plugin non debbano stabilire i meccanismi da utilizzare per visualizzare l'avanzamento in una determinata situazione. Un altro vantaggio sta nel fatto che la finestra di dialogo di avanzamento visualizzata con questi metodi fornisce un ottimo supporto per indicare quando un'operazione è bloccata e fornisce all'utente il controllo per risolvere il conflitto. Quando possibile, le operazioni di lunga durata devono essere eseguite utilizzando IProgressService#busyCursorWhile:


   IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
   progressService.busyCursorWhile(new IRunnableWithProgress(){
      public void run(IProgressMonitor monitor) {
         //do non-UI work
      }
   });

Questo metodo supporta inizialmente un cursore e lo sostituisce con una finestra di dialogo di avanzamento se l'operazione dura più a lungo della soglia di tempo specificata. Il vantaggio di questo metodo rispetto all'utilizzo di una finestra di dialogo di avanzamento sta nel fatto che se l'operazione è di breve durata, la finestra di dialogo di avanzamento non viene visualizzata. Se l'operazione deve aggiornare l'UI, è possibile sempre inviare un Display.asyncExec o Display.syncExec per eseguire il codice che modifica l'UI. Se un'operazione deve essere eseguita completamente nel thread dell'UI, è necessario richiamare IProgressService#runInUI. Inoltre, il vantaggio di questo metodo sta nel fatto che visualizza una finestra di dialogo di avanzamento se l'operazione è bloccata e fornisce il controllo all'utente.


   progressService.runInUI(
      PlatformUI.getWorkbench().getProgressService(),
      new IRunnableWithProgress() {
         public void run(IProgressMonitor monitor) {
            //do UI work
         }
      },
      Platform.getWorkspace().getRoot());
 

Il terzo parametro può essere null o una regola di pianificazione per l'operazione. In questo caso, si specifica l'elemento principale dello spazio di lavoro che blocca lo spazio di lavoro durante l'esecuzione dell'operazione dell'UI.

È anche possibile registrare con il servizio di avanzamento un'icona per una famiglia di lavori, in modo che la vista di avanzamento possa visualizzare l'icona accanto al lavoro in esecuzione. Di seguito viene riportato un esempio del modo in cui la generazione automatica è associata alla relativa icona:


   IProgressService service = PlatformUI.getWorkbench().getProgressService();
   ImageDescriptor newImage = IDEInternalWorkbenchImages.getImageDescriptor(
      IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC);
   service.registerIconForFamily(newImage, ResourcesPlugin.FAMILY_MANUAL_BUILD);
   service.registerIconForFamily(newImage, ResourcesPlugin.FAMILY_AUTO_BUILD);

Visualizzazione di una parte occupata

IWorkbenchSiteProgressService aggiunge l'API per la pianificazione dei lavori che modificano l'aspetto della parte di un workbench durante l'esecuzione del lavoro. Se il plugin esegue operazioni di sfondo che influiscono sullo stato di una parte, è possibile pianificare il lavoro mediante la parte, in modo che l'utente visualizzi il feedback che mostra che la parte è occupata. Di seguito viene riportato un esempio:


   IWorkbenchSiteProgressService siteService =
      (IWorkbenchSiteProgressService)view.getSite().getAdapter(IWorkbenchSiteProgressService.class);
   siteService.schedule(job, 0 /* now */, true /* use half-busy cursor in part */);

Proprietà di avanzamento per i lavori

Un insieme di proprietà predefinite è specificato in IProgressConstants , che può essere utilizzato per controllare il modo in cui un lavoro viene visualizzato nella vista di avanzamento. Le proprietà possono essere utilizzate per indicare la vista di avanzamento in cui inserire (IProgressConstants#KEEP_PROPERTY) il lavoro una volta completato o per indicare di inserire un lavoro (IProgressConstants#KEEPONE_PROPERTY) alla volta nella vista. È possibile anche associare un'azione (IProgressConstants#ACTION_PROPERTY) ad un lavoro. Quando ad un lavoro è associata un'azione, la vista di avanzamento mostra un collegamento ipertestuale in modo che l'utente possa eseguire l'azione. È possibile anche rilevare se il lavoro di un utente viene attualmente visualizzato in una finestra di dialogo di avanzamento (IProgressConstants#PROPERTY_IN_DIALOG). Un suggerimento viene visualizzato a destra della riga di stato quando è disponibile un'azione. Di seguito viene riportato un esempio in cui vengono utilizzate queste proprietà:


   Job job = new Job("Do Work") {
      public IStatus run(IProgressMonitor monitor) {
         // do some work then only keep the finished job in the progress view if
         // not running in the progress dialog
         Boolean inDialog = (Boolean)getProperty(IProgressConstants.PROPERTY_IN_DIALOG);
         if(!inDialog.booleanValue())
            setProperty(IProgressConstants.KEEP_PROPERTY, Boolean.TRUE);
      }
   };
   job.setProperty(IProgressConstants.ICON_PROPERTY, Plugin.getImageDescriptor(WORK_IMAGE));
   IAction gotoAction = new Action("Results") {
      public void run() {
         // show the results
      }
   };
   job.setProperty(IProgressConstants.ACTION_PROPERTY, gotoAction);
   job.setUser(true);
   job.schedule();

Lavori del workbench

Quando possibile, le operazioni di lunga durata devono essere eseguite al di fuori del thread dell'UI. Tuttavia, ciò non può sempre essere evitato quando lo scopo dell'operazione è quello di aggiornare l'UI. La sezione Problemi relativi ai thread SWT illustra come eseguire questa operazione utilizzando la Visualizzazione SWT. Il workbench definisce un lavoro speciale, UIJob, il cui metodo di esecuzione viene eseguito all'interno di un SWT asyncExec. Le sottoclassi di UIJob devono implementare il metodo runInUIThread anziché il metodo run.

WorkbenchJob estende UIJob in modo che il lavoro possa essere solo pianificato o eseguito quando il workbench è in esecuzione. Come sempre, è necessario evitare il lavoro eccessivo nel thread dell'UI, perché l'UI non viene aggiornata per tutta la durata del lavoro.

Informazioni particolari.