问题
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