public <T extends DomainObject> void taskCompleted(T obj, BackgroundCommandTask<T> task,
			TaskMonitor monitor) {

		obj.flushEvents();

		try {
			while (!monitor.isCancelled()) {
				BackgroundCommand<T> cmd;
				synchronized (this) {
					cmd = getNextCommand(obj);
					if (cmd == null) {
						// any late follow-on commands will require a new task
						task.setDoneQueueProcessing();
						break;
					}
				}
				Msg.debug(this, time() + "Start: " + cmd.getName());
				toolTaskMonitor.updateTaskCmd(cmd);
				long localStart = System.currentTimeMillis();
				cmd.applyTo(obj, monitor);
				cmd.taskCompleted();
				double totalTime = (System.currentTimeMillis() - localStart) / 1000.00;
				Msg.debug(this,
					time() + "Completed: " + cmd.getName() + " (" + totalTime + " secs)");
				obj.flushEvents();
			}
		}
		finally {
			try {
				if (monitor.isCancelled()) {
					clearQueuedCommands(obj);
					if (tool != null) {
						tool.setStatusInfo(task.getCommand().getName() + " cancelled");
					}
				}
			}
			finally {
				if (currentTask.isModal()) {
					modalTaskDialog.taskProcessed();
					modalTaskDialog = null;
				}
				else {
					toolTaskMonitor.taskCompleted(currentTask);
				}
			}
		}
		task.getCommand().taskCompleted();
		double totalTime = (System.currentTimeMillis() - startTaskTime) / 1000.00;
		Msg.debug(this,
			time() + "Task Completed: " + task.getTaskTitle() + " (" + totalTime + " secs)");
	}
Notification from the BackgroundCommandTask that it has completed; queued
or scheduled commands are executed.

@param obj domain object that supports undo/redo
@param task background command task that has completed
@param monitor task monitor
Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/mgr/ToolTaskManager.java