IntelliJ 15: How to interrupt a background task

Hi,

   in my IntelliJ plugin (EvoSuite) I want to run an expensive operation (which can take minutes/hours) on a background task. This can for example be done with:

MyTask task = new MyTask(...); // extends Task.Backgroundable
BackgroundableProcessIndicator progressIndicator = new MyIndicator(task); // extends BackgroundableProcessIndicator
ProgressManager.getInstance().runProcessWithProgressAsynchronously(task, progressIndicator);



this runs the task just fine, but the "Cancel" button from the IntelliJ GUI does not work. Well, it states that it is stopping the task, but it does not, as the thread running the task does not seem to be interrupted (in my code it waits on an external operation). Now, I found a workaround to this problem, but it is very ugly:

 
private class MyTask extends Task.Backgroundable{
    @Override
    public void
run(@NotNull ProgressIndicator progressIndicator) {

             thread = Thread.currentThread(); //save reference to the thread running this task
              ....
        }

 private class EvoIndicator extends BackgroundableProcessIndicator{

//        @Override  //can't override because final
//        public void cancel(){
//        }

        @Override
        protected void
delegateRunningChange(@NotNull IndicatorAction action) {
            try {
                Field f = com.intellij.openapi.progress.util.AbstractProgressIndicatorExBase.class.getDeclaredField("CANCEL_ACTION");
                f.setAccessible(true);
                Object obj = f.get(null);
                if(action.equals(obj)){
                    thread.interrupt();
                }
            } catch (Exception e) {
            }
            super.delegateRunningChange(action);
        }



this solution does seem to work. However, is there any cleaner way to achive the same results? (eg, using reflection on a library is just a receipe for a lot of maintainance headaches in the future...)

cheers

Andrea

1 comment
Comment actions Permalink

You should implement your task in the way that it supports cancellation.

To achieve this, you could check "progressIndicator.checkCanceled()" periodically during your task execution (in your task "run()" method) and finish the task correspondingly if the check indicates the task was cancelled.

1

Please sign in to leave a comment.