2

显然,所有 Eclipse/SWT 管理繁忙鼠标指示器的方式都是

BusyIndicator.showWhile(Runnable synchronousStuffToDo)

但是,我有一个从根本上面向事件的项目,其中“要做的事情”不会发生在连续的执行行中:一个动作被排序,一个持续回调被提供给执行管理器。因此,我没有什么有意义的东西可以放入该synchronousStuffToDo可运行文件中。

是否有另一种异步操作繁忙指示器的方法,无论多么低级和笨拙,但与平台无关,这意味着两个单独的方法调用,“激活它”和“停用它”?

我应该补充ProgressMonitorDialog这个问题,因为它似乎遇到了同样的问题。是的,在该ProgressMonitorDialog#run方法中,内部事件循环将被旋转,但 SWT 事件循环只是我的执行管理器之一,因此链仍然会中断。显然,如果没有这个类,我什至无法显示进度监视器,除非我从较低级别的原语重新实现。

4

3 回答 3

6

您无法Cursor使用BusyIndicator该类来操作。您可以在后台运行作业时调用以下 util 方法来显示忙碌图标Thread

public static void imBusy(final boolean busy){

    Display.getDefault().asyncExec(new Runnable()
    {
        @Override
        public void run()
        {
            Shell shell = Display.getDefault().getActiveShell();
            if(busy){ //show Busy Cursor
                Cursor cursor = Display.getDefault().getSystemCursor(SWT.CURSOR_WAIT);          
                shell.setCursor(cursor);
            }else{  
                shell.setCursor(null);
            }   
        }
    });

}
于 2013-06-14T21:14:52.803 回答
0

您的可运行文件应该等待任务完成。例如(用浏览器编写的代码,不会编译 - 我忽略了异常):

final Object condition = new Object();
BusyIndicator.showWhile(new Runnable() {
    public void run() {
        synchronized(condition) {
            while (!isMyTaskDoneFlag()) {
                condition.wait();
            }
        }
    }
});
doTask(new MyTask() {
    public void perform() {
        try {
            // Task logic
            ...
        } finally {
            // When done
            setMyTaskDoneFlag();
            synchronized(condition) {
                condition.notify();
            }
        }
    }
});

确保任务中的所有代码路径不要忘记取消阻止可运行文件。几乎相同的方法可以用于进度监视器 - 您可以唤醒您的可运行对象以更新进度监视器值。

注意:您需要确保等待的可运行对象不在 SWT 线程上执行(例如,设置fork为是​​否true正在运行监视器),否则您的应用程序将变得无响应。

于 2013-06-14T23:36:39.047 回答
0

我在我现在正在处理的旧 SWT 应用程序中找到了一个解决方案(我不是特别喜欢,但它确实有效)。它使用BusyIndicator#showWhile,它在里面做的同步的东西是:

  1. 在后台线程中启动异步任务
  2. 循环等待后台线程完成,同时显式旋转 SWT 事件循环:
while (!taskDone){
    if (!display.readAndDispatch() && !shell.isDisposed()) {
        display.sleep();
    }
    taskDone = //check for task progress
    //update something on the main window status bar
}

我正在尝试将其转换为更清洁的东西(按照 Marko 的建议):

  1. 设置忙碌图标
  2. 提交后台任务
  3. 取消设置忙碌图标

但我不确定什么最适合更新状态栏(后台任务实际上是远程调用,因此它们的线程在完成之前被阻塞)。我正在考虑有一个专用线程来检测后台作业何时运行并相应地更新状态栏(更新只是一条展开的虚线,没有特定于任务),但是为此使用线程似乎有点浪费.

于 2016-05-06T06:34:17.540 回答