等待使用 Display::asyncExec() 提交给 SWT UI 线程的所有 Runnable 完成

发布于 2024-12-17 10:45:13 字数 331 浏览 1 评论 0原文

有没有办法等待通过 asyncExec(...) 提交到 SWT UI 线程的所有 Runnable 完成?

背景:

我有一个长时间运行的操作,除其他外,它还触发以下事件:依次通过 Display 的 asyncExec(...) 实例方法将 Runnables 提交到 SWT UI 线程。

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

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

Is there a way to wait for all Runnables submitted to the SWT UI Thread via asyncExec(...) to finish?

Background:

I have a long-running operation, which among other things is triggering events that in turn submit Runnables to the SWT UI thread via the asyncExec(...) instance method of Display.

The progress of the long-running operation is shown in a ProgressMonitorDialog, and I would like to close the dialog only after the UI thread has finished executing the Runnables.

Changing the calls from asyncExec(...) to syncExec(...) is not an option, as the latter is not desired when the events are triggered from other contexts.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

狠疯拽 2024-12-24 10:45:13

org.eclipse.swt.widgets.Display.readAndDispatch() 将处理事件队列中的事件,如果没有更多事件需要处理,则返回 false。但您可能不想在它处理事件时使用它。

asyncExec(*) 是一个 FIFO 队列(尽管操作系统图形事件取代了 asyncExec),因此您可以完成大部分长时间运行的操作处理,然后将最终的 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);
}

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

编辑:潜在的其他选项

创建您自己的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();

org.eclipse.swt.widgets.Display.readAndDispatch() will process an event from the event queue and return false if there are no more events to process. But you probably don't want to use this as it processes an event.

asyncExec(*) is a FIFO queue (although OS graphics events supersede the asyncExecs), so you could do most of your long-running op processing and then place a final asyncExec in the queue:

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);
}

In theory, all of the other asyncExecs spawned from your long running op will be finished by the time you get to the last one.

EDIT: potential other option

Create your own org.eclipse.core.runtime.jobs.Job and then join() it at the end:

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;
    }
}

To use it, increment() it every time you are going to fire off events, and have them decrement it when they're done (You have to make sure they decrement it no matter what exception is thrown :-)

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();
墨落成白 2024-12-24 10:45:13

谢谢,我最终得到了以下结果。我认为这是一个非常干净的解决方案。顺便说一句,如果我有足够的声誉,我会投票给你的答案:)

public class SWTThreadingUtils
{

    public static void waitForAsyncExecsToFinish(Display display)
    {
        Object waitObj = new Object();

        display.asyncExec(new DummyRunnable(waitObj));
        synchronized (waitObj) 
        {
            try {
                waitObj.wait();

            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }


    private static class DummyRunnable implements Runnable
    {
        private Object waitObj;

        public DummyRunnable(Object waitObj)
        {
            this.waitObj = waitObj;
        }

        @Override
        public void run()
        {
            synchronized (waitObj)
            {
                waitObj.notify();
            }
        }    
    }

}

Thanks, I ended up with the following. I think it is a pretty clean solution. By the way I would upvote your answer if I had enough reputation for that :)

public class SWTThreadingUtils
{

    public static void waitForAsyncExecsToFinish(Display display)
    {
        Object waitObj = new Object();

        display.asyncExec(new DummyRunnable(waitObj));
        synchronized (waitObj) 
        {
            try {
                waitObj.wait();

            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }


    private static class DummyRunnable implements Runnable
    {
        private Object waitObj;

        public DummyRunnable(Object waitObj)
        {
            this.waitObj = waitObj;
        }

        @Override
        public void run()
        {
            synchronized (waitObj)
            {
                waitObj.notify();
            }
        }    
    }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文