SWT中syncExec()问题

7
这是我在 StackOverflow 上的第一个问题(对我的英语感到抱歉)。我会尽力清晰地解释问题。
我有一个 SWT 应用程序,其中包含一个前台 Jade 应用程序,它具有用于显示应用程序持续时间的进度条。为了刷新此进度条,我使用以下代码:
if(Display.getCurrent() != null) {
    progress.run();
}
else {
   sShell.getDisplay().syncExec(progress);
}

进度是:

Runnable progress = new Runnable() {
    public void run () {
        if (progressBar.isDisposed ()) 
            return;
        int percentage= (numStep*100)/maxSteps;
        progressBar.setSelection(percentage);
        if (numStep >= maxSteps){
            label1.setText("The simulation has been completed.");
            button.setEnabled(true);
        }    
    }
};

我尝试分析这个Runnable所需的时间,发现它是恒定的,但是当我分析这行代码时 sSehll.getDisplay().syncExec(progress) 所需时间不同(从0ms到XXXXms)。
我已经阅读了这篇文章:

syncExec(Runnable runnable) 会导致当前线程(如果它与显示器的用户界面线程不同)等待runnable完成。

但是Runnable的时间是恒定的...
有人能指导我吗?我不明白为什么有时需要3分钟,而有时则不需要。
谢谢

1
+1,欢迎来到StackOverflow!我已经为您重新格式化了代码,但是您不必为自己的英语道歉 :) - Peter Lang
感谢您。我早就知道这个网站,但今天终于被鼓励参与了。 - Michel
2个回答

3
SWT Display类中有两种方法,syncExec和aSyncExec。它们都用于在非UI线程中更新UI。当您调用它们时,实际上是在告诉UI线程:您有一些工作需要在有机会的时候完成。因此,UI线程将继续其当前的工作,并在某个时刻执行您要求执行的任务。执行的时间将根据UI线程此时正在执行的其他工作而异。
aSyncExec和syncExec的区别在于调用它们的代码是否等待执行完成。如果调用aSyncExec,那么您调用线程中的下一条语句将立即执行。如果调用syncExec,则调用线程将停止并等待UI线程实际执行代码并返回结果。通过计算执行syncExec所需的时间,您不仅计时了run方法的执行时间,还计时了UI线程实际开始运行它之前的时间。
不要尝试在此处交换syncExec和aSyncExec。如果您计算aSyncExec执行所需的时间,您会发现它甚至更快。但这是因为您只计时了告诉UI线程有任务需要完成的时间,而没有计时实际完成任务所需的时间。

但是没有立即执行它的方法吗? - Michel
不。它应该执行得相当快,除非您的UI线程正在做很多工作(如果是这种情况,您可能需要查看它正在做什么,并尝试在不同的线程中使其工作)。如果确实需要3分钟,那么我猜测您的UI线程正在做其他事情?它是否正在进行与UI相关的工作? - DaveJohnston
那么这项工作将不得不留在主UI线程中,任何其他请求该线程执行工作的操作都必须等待它们的轮到。 - DaveJohnston

1
根据Display类文档syncExec的作用是:

在下一个合适的机会,导致可运行对象的run()方法被用户界面线程调用。调用此方法的线程将被挂起,直到可运行对象完成。如果将可运行对象指定为null,则只会唤醒用户界面线程。

因此,您的run方法在恒定时间内运行,但Display对象可能不会立即调用它。

我记得在阅读文档时看到过,但是没有强制执行的方法吗? - Michel
1
如果您的syncExec需要三分钟才能完成,那么您可能在SWT线程中执行了代码,应该将其放入后台线程。这样做可以让UI再次平稳运行。 - Christopher Oezbek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接