Time for action – using null progress monitors and sub monitors

When a method uses progress monitors extensively, it is inelegant to keep checking whether the monitor is null or not. Instead, the progress monitor can be replaced with a NullProgressMonitor, which acts as a no-op for all monitor calls.

  1. Update the checkDozen to use a NullProgressMonitor if null is passed:
    private void checkDozen(IProgressMonitor monitor) {
      if (monitor == null)
        monitor = new NullProgressMonitor();

    This allows the remainder of the method to run without modification and saves any NullPointerException errors that may result.

  2. A similar result to both the NullProgressMonitor and a SubProgressMonitor with a wrapper/factory class called SubMonitor. This provides factory methods to wrap the monitor and create child progress monitors:
    protected IStatus run(IProgressMonitor monitor) {
      try {
        SubMonitor subMonitor = 
          SubMonitor.convert(monitor,"Preparing", 5000);
        for (int i = 0; i < 50 && !subMonitor.isCanceled(); i++) {
          if (i == 10) {
            subMonitor.subTask("Doing something");
          } else if (i == 12) {
            checkDozen(subMonitor.newChild(100));
            continue;
          } else if (i == 25) {
            subMonitor.subTask("Doing something else");
          } else if (i == 40) {
            subMonitor.subTask("Nearly there");
          }
          Thread.sleep(100);
          subMonitor.worked(100);
        }
      } catch (InterruptedException e) {
      } finally {
        monitor.done();
      }
    }
  3. Running the code has the same effect as the previous one, but is more efficient. Note that the subMonitor is used everywhere in the method until the end, where monitor is used to invoke done.

What just happened?

The NullProgressMonitor and SubProgressMonitor were replaced by a SubMonitor. To convert an arbitrary IProgessMonitor into a SubMonitor, use the convert factory method. This has the advantage of testing for null (and using an embedded NullProgressMonitor if necessary) as well as facilitating the construction of SubProgressMonitor instances with the newChild call.

Note

Note that the contract of SubMonitor requires the caller to invoke done on the underlying progress monitor at the end of the method, so it is an error to do an assignment like monitor = SubMonitor.convert(monitor) in code.

Since the isCancelled check will ultimately call the parent monitor, it doesn't strictly matter whether it is called on the sub monitor or the parent monitor. However, if the parent monitor is null, invoking it on the parent will result in a NullPointerException, whereas the SubProgressMonitor will never be null.

In situations where there will be lots of recursive tasks, the SubProgessMonitor will handle nesting better than instantiating a SubProgressMonitor each time. That's because the implementation of the newChild doesn't necessarily need to create a new SubMonitor instance each time; it can keep track of how many times it has been called recursively.

The SubMonitor also has a setWorkRemaining call, which can be used to reset the amount of work for the outstanding progress monitor. This can be useful if the job doesn't know at the start how much work is there to be done, but it does become known later in the process.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.207.174