Eclipse RCP: Stopping a thread/job that freezes

我们两清 提交于 2019-12-13 04:44:02

问题


I have a method:

TraceData.getTraceData(true);

This trace method takes very long or freezes if the external interface is not configured properly. So it does not even return a null. It just hangs.

In this case I want to implement a pop up dialog box with a button "Cancel" to stop this method.

So I created a Job to run this method:

    final Job job = new Job("Trace Job") {
      @Override
      protected IStatus run(IProgressMonitor monitor) {


          TraceData.getTraceData(true);


          Display.getDefault().asyncExec(new Runnable() {
          @Override
          public void run() {
              MessageDialog.openInformation(shell, "Your Popup ","Your job has finished.");
          }
        });
        return Status.OK_STATUS;
      }
    };

Then I created a dialog box with a single option to stop the trace.

 Shell shell2 = new Shell();
 final MessageBox dialog = new MessageBox(shell2, SWT.ICON_QUESTION | SWT.CANCEL);

 dialog.setText("Tracing");
 dialog.setMessage("Cancel Tracing ?");

 int cancelTrace = dialog.open();

This dialog box should automatically disappear when the if tracing is done. So the main thread should stop at this dialog box and wait for the trace to be finished. Or if the user clicks cancel it will stop the trace.

EDIT

Thanks to Alexander I came up with following, but it still has a couple of issues. I needed to put false for the fork in dialog.run(), otherwise I a get SWT thread access error like this. Also I used the Display.getDefault().asyncExec() before to update the my UI before, but here it is not being activated. Lastly the cancel button is not working, i.e. it cannot be pressed. But the progress bar is working.

        ProgressMonitorDialog dialog = new ProgressMonitorDialog(Display.getDefault().getActiveShell());
        try {
            dialog.run(false, true, new IRunnableWithProgress() {

                @Override
                public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {

                    monitor.beginTask("Tracing", 10 );

                    for(int i = 0; i < 10; i++){

                        // Check if the user pressed "cancel" or method has finished
                        if(monitor.isCanceled() || finished == true){
                            System.out.println("Cancel Pressed or Finished");
                            monitor.done();
                            return;
                        }else{
                            Display.getDefault().readAndDispatch();
                        }

                        if (i == 0){    // run only once
                            System.out.println("Here");
                            Display.getDefault().asyncExec(new Runnable() {
                              @Override
                              public void run() {
                                try {
                                    System.out.println("Start Trace");
                                    Thread.sleep(4000);  // represents long method

                                    finished = true;
                                } catch (InterruptedException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }
                              }
                            });
                        }

                        // Optionally add subtasks
                        monitor.subTask("Time passed: " + (i * 500) + " ms");

                        Thread.sleep(500);

                        // Tell the monitor that you successfully finished one item of "workload"-many
                        monitor.worked(1);

                    }
                    // You are done
                    monitor.done();
                }
            });
        } catch (InvocationTargetException | InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }


回答1:


What you could use is ProgressMonitorDialog: it has possibility to cancel the work and show your progress.

ProgressMonitorDialog dialog = new ProgressMonitorDialog(Display.getDefault().getActiveShell());
        try {
            dialog.run(true, true, new IRunnableWithProgress() {

                @Override
                public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
                    monitor.beginTask("Tracing", 100);
                    while(!monitor.isCanceled()) {
                        Display.getDefault().readAndDispatch();
                        // Do your work here
                    }
                }
            });
        } catch (InvocationTargetException | InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

This example would probably needs to be adjusted for your requirements and TraceData.getTraceData(true); implementation. Probably you wouldn't use while cycle but rather checking time to time if dialog is cancelled.

I think that the main problem you have there is the part where you put Thread to sleep. Since you are executing it in the UI thread, you are actually putting the UI Thread to sleep. That is why neither cancel button, nor other part, where you want to update your UI in asynchExec is working.

I'd suggest you to create a Job. This will create another non-UI Thread, which can be used for checking, if monitor is cancelled or updating some state variables or whatever.



来源:https://stackoverflow.com/questions/26756068/eclipse-rcp-stopping-a-thread-job-that-freezes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!