package cz.cuni.lf1.lge.ThunderSTORM.util; import cz.cuni.lf1.lge.ThunderSTORM.UI.MacroParser; import ij.IJ; import javax.swing.*; import java.util.concurrent.ExecutionException; /** * This class is used for post-processing modules, where some of the calls might be time consuming, * therefore they are performed in a separate thread to avoid blocking of GUI. However, if ran from * macro, the blocking call is desirable so that the next macro command waits until the current * operation is finished to avoid race conditions. */ public abstract class WorkerThread<T> { /** * Implement what the worker is supposed to do. * * @return result of the operation */ protected abstract T doJob(); /** * Implement what to do with the results of the operation. * * @param result result from `doJob()` */ protected void finishJob(T result) { // } /** * Main method, which checks if the method was called from macro or directly from GUI. */ public void execute() { if (MacroParser.isRanFromMacro()) { // blocking call finishJob(doJob()); exFinally(); } else { // run in background new SwingWorker<T, Void>() { @Override public T doInBackground() { return doJob(); } @Override protected void done() { try { finishJob(get()); } catch (InterruptedException ex) { exCatch(ex); } catch (ExecutionException ex) { exCatch(ex); } finally { exFinally(); } } }.execute(); } } /** * Since exceptions can be catched only within the active thread, this method is * called when an exception is catched. * * @param ex an exception */ public void exCatch(Throwable ex) { IJ.handleException(ex); } /** * This method is called automatically at the end of `finishJob()` as part of try-catch-finally block. * See `exCatch()`. */ public void exFinally() { // } }