Reporting progress

Long running jobs (those lasting more than a second) should report progress to the IProgressMonitor that is passed to the job's run method. The workbench progress view will show all progress messages and units of completed work given to this monitor.

The supplied progress monitor should also be used to check for cancellation requests made from the progress view. When a user (or plug-in using job API) attempts to cancel a job, the IProgressMonitor method isCanceled() will return true. It is the job's responsibility to frequently check the cancellation status of a job and respond to a cancellation by exiting the run method as soon as possible once it detects a cancellation. The following run method reports progress and responds to job cancellation:

   public IStatus run(IProgressMonitor monitor) {
      final int ticks = 6000;
      monitor.beginTask("Doing some work", ticks);
      try {
         for (int i = 0; i < ticks; i++) {
            if (monitor.isCanceled())
               return Status.CANCEL_STATUS;
            monitor.subTask("Processing tick #" + i);
            //... do some work ...
            monitor.worked(1);
         }
      } finally {
         monitor.done();
      }
      return Status.OK_STATUS;
}

The beginTask method is used to name the task in the corresponding progress view and to establish the total amount of work to be done so that the view can compute progress. The subTask messages will appear as a child in the progress tree as work is done. The progress view will calculate and display a percent completion based on the amount of work reported in the worked calls.

Progress monitors and the UI

As you can see, the IProgressMonitor class is designed with corresponding UI support in mind. The platform's UI plug-in provides support so that the workbench can show progress for jobs that are running. You can set up your jobs with this in mind, so that you can control how they are presented.

See Workbench Concurrency Support for a detailed look at the APIs available for showing progress for jobs.

System jobs

What if your job is a low-level implementation detail that you don't want to show to users? You can flag your job as a system job. A system job is just like any other job, except the corresponding UI support will not set up a progress view or show any other UI affordances associated with running a job. If your job is not either directly initiated by a user, or a periodic task that can be configured by a user, then your job should be a system job. The protocol for setting a system job is simple:

   class TrivialJob extends Job {
      public TrivialJob() {
         super("Trivial Job");
         setSystem(true);
      }
      ...
   }

The setSystem call must be made before the job is scheduled. An exception will be triggered if you attempt this call on a job that is currently waiting, sleeping, or running.

User jobs

If your job is a long running operation that is initiated by a user, then you should flag your job as a user job. A user job will appear in a modal progress dialog that provides a button for moving the dialog into the background. The workbench defines a user preference that controls whether these dialogs are ever modal. By defining your job as a user job, your progress feedback will automatically conform with the user preference for progress viewing. The protocol for setting a user job is similar:

   class TrivialJob extends Job {
      public TrivialJob() {
         super("Trivial Job");
         setUser(true);
      }
      ...
   }

The setUser call must also be made before the job is scheduled.

Progress groups

Progress groups are another mechanism that can be used to influence the way that a job is shown in the UI. When it is more appropriate to show the aggregate progress of several related jobs in the UI, a special IProgressMonitor that represents a group of related jobs can be created. This monitor is created using IJobManager protocol. The following snippet shows how to create a progress group and associate it with a job.

   ...
   IJobManager jobMan = Job.getJobManager();
   myGroup = jobMan.createProgressGroup();
   job.setProgressGroup(myGroup, 600);  // specify the units of work the job needs to show.
   job.schedule()
   ...

The group facility allows plug-ins to break tasks into multiple jobs if needed, but to report them to the user as if they are a single task. The progress group monitor will handle the details for computing the percentage completion relative to all of the jobs in the group.

A job must be placed into the progress group before it is scheduled. After a job finishes running, its reference to the progress group is lost. If the job is to be scheduled again, it must be set into the group once again before it is scheduled.