有没有办法等待通过asyncExec(...)提交给SWT UI线程的所有可运行对象?

背景:

我有一个长期运行的操作,除其他外,该操作正在触发一些事件,这些事件又通过Display的asyncExec(...)实例方法将Runnables提交给SWT UI线程。

长时间运行的操作的进度显示在ProgressMonitorDialog中,我想仅在UI线程完成执行Runnable之后关闭对话框。

不能将调用从asyncExec(...)更改为syncExec(...),因为从其他上下文触发事件时不需要后者。

最佳答案

org.eclipse.swt.widgets.Display.readAndDispatch()将处理事件队列中的事件,如果没有更多事件要处理,则返回false。但是您可能不想在处理事件时使用它。
asyncExec(*)是一个FIFO队列(尽管OS图形事件取代了asyncExecs),因此您可以执行大部分长时间运行的op处理,然后将最终的asyncExec放入队列中:

final boolean[] done = new boolean[1];
Runnable r = new Runnable() {
  public void run() {
    done[0] = true;
  }
};
// now wait for the event somehow.  The brute force method:
while (!done[0]) {
  Thread.sleep(200);
}

从理论上讲,从长时间运行的操作中产生的所有其他asyncExecs都将在您到达最后一个时完成。

编辑:潜在的其他选择

创建您自己的org.eclipse.core.runtime.jobs.Job,然后在最后对它进行join():
public static class RefCountJob extends Job {
    public RefCountJob() {
        super("REF_COUNT");
    }

    int count = 0;

    public void increment() {
        count++;
    }

    public void decrement() {
        count--;
    }

    @Override
    protected IStatus run(IProgressMonitor monitor) {
        monitor.beginTask("WAITING", IProgressMonitor.UNKNOWN);
        while (count > 0) {
            Thread.sleep(200);
            monitor.worked(1);
        }
        monitor.done();
        return Status.OK_STATUS;
    }
}

要使用它,请在每次要触发事件时将它递增(),并在事件完成时让它们递减(无论抛出什么异常,您都必须确保它们递减:-)
RefCountJob ref = new RefCountJob();
// ... do stuff, everybody increments and decrements ref
ref.increment();
// ... do more stuff
ref.increment();
// at the end of your long-running job
ref.schedule();
ref.join();

07-27 20:33