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) {
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.
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;
}
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.
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 {
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.
public TrivialJob() {
super("Trivial Job");
setSystem(true);
}
...
}
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 {
The setUser call must also be made before the job is
scheduled.
public TrivialJob() {
super("Trivial Job");
setUser(true);
}
...
}
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.
...
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.
IJobManager jobMan = Platform.getJobManager();
myGroup = jobMan.createProgressGroup();
job.setProgressGroup(myGroup, 600); // specify the units of work the job needs to show.
job.schedule()
...
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.