Suporte de Coincidência do Workbench

Observamos que a estrutura da UI de JFace fornece suporte básico para mostrar o progresso da tarefa em um diálogo (consulte Operações de longa execução para obter detalhes). Em Infra-estrutura de coincidência, revisamos o suporte do tempo execução da plataforma para coincidência e operações de longa execução. Agora observaremos como a UI da plataforma aprimora essa infra-estrutura no pacote de org.eclipse.ui.progress. Esse pacote fornece a UI para mostrar o progresso da tarefa no workbench e define suporte adicional para as tarefas que são executadas no encadeamento da UI.

Antes de introduzirmos as novas APIs, vamos começar revisando alguns conceitos. Primeiramente, temos que distinguir entre os diferentes tipos de operações de segundo plano:


Em um ambiente em que várias coisas podem estar acontecendo ao mesmo tempo, o usuário precisa:

A seguir, entraremos em detalhes sobre como as novas APIs podem ser utilizadas.

Serviço de progresso

O serviço de progresso do workbench (IProgressService) é a interface principal do suporte de progresso do workbench. Pode ser obtido a partir do workbench e, em seguida, utilizado para mostrar progresso para as operações de segundo plano e as operações que são executadas no encadeamento da UI. A finalidade principal dessa classe é fornecer um ponto de compras para execução das operações, removendo a necessidade de desenvolvedores de plug-in para decidir qual mecanismo deve ser utilizado para mostrar progresso em uma determinada situação. Outra vantagem é que o diálogo de progresso mostrado com esses métodos fornece um bom suporte para indicar quando uma operação está bloqueada por outra e fornece o controle do usuário para resolver o conflito. Onde possível, as operações de longa execução devem ser executadas utilizando IProgressService#busyCursorWhile:


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

Este método inicialmente colocará um cursor ocupado e o substitui por um diálogo de progresso se a operação durar mais tempo que um limite de tempo especificado. A vantagem desse método em utilizar um diálogo de progresso é que se a operação for executada em pouco tempo, o diálogo de progresso não será mostrado. Se a sua operação deve atualizar a UI, você sempre pode enviar um Display.asyncExec ou Display.syncExec para executar o código que modifica a UI. Se uma operação deve ser executada na sua totalidade no encadeamento da UI, em seguida, você deve chamar IProgressService#runInUI. Novamente, a vantagem desse método é que um diálogo de progresso será exibido se a operação for bloqueada e der o controle ao usuário.


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

O terceiro parâmetro pode ser nulo ou uma regra de planejamento para a operação. Neste caso, estamos especificando a raiz do espaço de trabalho que essencialmente travará o espaço de trabalho enquanto esta operação de UI é executada.

Também é possível registrar, com o serviço de progresso, um ícone para uma família de tarefas para que a visualização de progresso possa mostrar o ícone próximo à tarefa em execução. Aqui está um exemplo de como a autoconstrução está associada ao seu ícone:


   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);

Mostrando que uma Peça está Ocupada

IWorkbenchSiteProgressService inclui API para as tarefas de planejamento que alteram a aparência de uma peça do workbench enquanto a tarefa está em execução. Se o seu plug-in estiver executando operações em segundo plano que afetam o estado de uma peça, você pode planejar a tarefa via peça e o usuário obterá feedback de que a peça está ocupada. A seguir encontra-se um exemplo:


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

Propriedades de Progresso para Tarefas

Há um conjunto de propriedades predefinidas definido em IProgressConstants que pode ser utilizado para controlar como uma tarefa é mostrada na visualização de progresso. Isso pode ser utilizado para dizer à visualização de progresso para manter IProgressConstants#KEEP_PROPERTY) sua tarefa na visualização depois de ter sido concluída ou manter uma (IProgressConstants#KEEPONE_PROPERTY) tarefa de cada vez na visualização. Também é possível associar uma ação (IProgressConstants#ACTION_PROPERTY) a uma tarefa. Quando uma tarefa tem uma ação associada, a visualização de progresso mostra um hyperlink para que um usuário possa executar a ação. Também é possível descobrir se uma tarefa do usuário está sendo mostrada atualmente em um diálogo de progresso IProgressConstants#PROPERTY_IN_DIALOG). Uma sugestão é fornecida na parte inferior direita da linha de status quando uma ação está disponível. Aqui está um exemplo que utiliza essas propriedades:


   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();

Tarefas do Workbench

Onde possível, as operações de longa execução devem ser executadas fora do encadeamento da UI. No entanto, isso não pode ser sempre evitado quando a finalidade da operação é atualizar a UI. Problemas de encadeamento SWT explica como isso pode ser feito utilizando SWT Exibir. O workbench define uma tarefa especial, UIJob, cujo método de execução é executado dentro de um asyncExec de SWT. As subclasses de UIJob devem implementar o método runInUIThread em vez do método de execução.

WorkbenchJob estende UIJob para que a tarefa possa ser somente planejada ou executada quando o workbench está em execução. Como sempre, você deve evitar trabalho excessivo no encadeamento UI porque a UI não será atualizado para a duração da Tarefa da UI.

Avisos legais.