/
How to report progress from long-running tasks

How to report progress from long-running tasks

Using progress monitor arguments

The class com.bc.ceres.ProgressMonitor is generally used to report progress in log running tasks. Many framework callbacks provide an instance of this interface to client functions.

void archiveInternet(ProgressMonitor pm) {
	try {
    	pm.beginTask("Archiving internet", 100);
		// Here: perform 20% of the work (download)
		pm.worked(20);
		// Here: perform 50% of the work (zip)
		pm.worked(50);
		// Here: perform remaining 30% work (copy)
		pm.worked(30);
	} finally {
		pm.done();
	}
}

Or pass sub-progess monitors to sub-functions:

void archiveInternet(ProgressMonitor pm) {
	try {
    	pm.beginTask("Archiving internet", 100);
		// Here: perform 20% of the work (download)
		downloadInternet(SubProgressMonitor.create(pm, 20));
		// Here: perform 50% of the work (zip)
		zipDownloadedInternet(SubProgressMonitor.create(pm, 50));
		// Here: perform remaining 30% work (copy)
		copyInternetZip(SubProgressMonitor.create(pm, 30));
	} finally {
		pm.done();
	}
}

Not shown in the code above is the check for cancelation. A user may have requested to cancel a long-running task. This is reported through the ProgressMonitor.isCanaceled() method. 

void archiveInternet(ProgressMonitor pm) {
	...
	for (...) {
		...
		if (pm.isCancelled()) {
		 	return; // or throw new CanceledException();
		}
        ...
	}
	...
}

Calling of methods that take a progress monitor argument 

If you can't or don't want to report progress you can simply pass a null progress monitor (but don't pass null):

 

archiveInternet(ProgressMonitor.NULL);

From command-line tools, you can use:

archiveInternet(new PrintWriterProgressMonitor(System.out));

From GUI code, we ustilise the adapter class org.esa.snap.rcp.util.ProgressHandleMonitor to report progress through ProgressMonitor interface but using NetBeans progress bars. As long running tasks should not be called from the Swing event dispatcher thread (EDT), we will have to create or reuse background threads to do so. The NetBeans org.netbeans.api.progress.ProgressUtils API provides some useful methods for this:

ProgressHandleMonitor pm = ProgressHandleMonitor.create("Archiving internet");
Runnable operation = () -> {
	archiveInternet(pm);
};
ProgressUtils.runOffEventThreadWithProgressDialog(operation, "Archiving internet", 
                                                  pm.getProgressHandle(), 
                                                  true, 
                                                  50,  // time in ms after which wait cursor is shown
                                                  1000);  // time in ms after which dialog with "Cancel" button is shown

Or using the NetBeans class org.openide.util.RequestProcessor:

RequestProcessor.getDefault().post(() -> {
	ProgressHandle handle = ProgressHandleFactory.createHandle("Archiving internet");
	ProgressMonitor pm = new ProgressHandleMonitor(handle);
	archiveInternet(pm);
});

See https://github.com/senbox-org/snap-desktop/blob/master/snap-rcp/src/main/java/org/esa/snap/rcp/util/ProgressHandleMonitor.java.

Documentation of NetBeans Progress API:

 

In older code you will find uses of the com.bc.ceres.swing.progress.ProgressMonitorSwingWorker class. Don't use it as it will cause the main frame to go into background and let other desktop windows hide it. Very annoying for users (and us developers).

 

 

 

 

Related content

Operator Implementation Guidelines
Operator Implementation Guidelines
More like this
How to hook into start-up and shutdown phase
How to hook into start-up and shutdown phase
More like this
How to create a Toolbox for SNAP
How to create a Toolbox for SNAP
Read with this
GPF Workflows
GPF Workflows
More like this
How to integrate an external tool in SNAP
How to integrate an external tool in SNAP
Read with this
Bulk Processing with GPT
Bulk Processing with GPT
More like this