网站建设数据库软件英文,福州网站优化公司,视频解析wordpress,岳阳网站建设开发大多数用户界面#xff08;UI#xff09;工具包都是单线程的#xff0c; SWT也不例外。 这意味着必须仅从单个线程#xff08;即所谓的UI线程#xff09;访问UI对象。 另一方面#xff0c;应在后台线程中执行长时间运行的任务#xff0c;以使UI保持响应。 这使得后台线程… 大多数用户界面UI工具包都是单线程的 SWT也不例外。 这意味着必须仅从单个线程即所谓的UI线程访问UI对象。 另一方面应在后台线程中执行长时间运行的任务以使UI保持响应。 这使得后台线程需要排队在UI线程上执行更新而不是直接访问UI对象。 为了安排代码在UI线程上执行SWT提供了Display asyncExec和syncExec方法。 显示asyncExec与syncExec 虽然这两种方法都将参数放在队列中以便在UI线程上执行但是它们在执行或不执行之后的操作不同。 顾名思义asyncExec异步工作。 它在可运行变量入队后立即返回并且不等待其执行。 而syncExec处于阻塞状态因此确实要等到代码执行完毕。 根据经验只要不依赖计划代码的结果即可使用asyncExec例如仅更新小部件以报告进度。 如果计划的代码返回了与进一步控制流相关的内容例如在阻止对话框中提示输入那么我将选择syncExec。 例如如果后台线程想要报告已完成工作的进度则最简单的形式可能如下所示 progressBar.getDisplay().asyncExec( new Runnable() {public void run() {progressBar.setSelection( ticksWorked );}
} ); asyncExec计划“在下一个合理的机会”如JavaDoc所说在UI线程上执行可运行对象。 不幸的是上面的代码可能会不时地失败并会出现一个放置小部件的异常 或更确切地说是一个SWTException其代码 SWT.ERROR_WIDGET_DISPOSED。 因此原因是进度条在被访问时可能不再存在即调用setSelection。 尽管我们仍然保留着对小部件的引用但是由于小部件本身已被废弃因此并没有太大用处。 解决方案显而易见代码必须首先测试该小部件是否仍然存在然后再对其进行操作 progressBar.getDisplay().asyncExec( new Runnable() {public void run() {if( !progressBar.isDisposed() ) {progressBar.setSelection( workDone );}}
} ); 看起来很明显一次又一次地执行这种检查是很乏味的。 您可能想在Eclipse bugzilla中搜索“ widget处置”以了解此问题的发生频率。 因此我们提取了一个封装检查的辅助类。 new UIThreadSynchronizer().asyncExec( progressBar, new Runnable() {public void run() {progressBar.setSelection( workDone );}} ); UIThreadSynchronizers asyncExec方法期望将小部件作为其第一个作为上下文的参数。 上下文小部件是指如果可运行的部件多于一个则将受可运行部件或合适的父部件影响的部件。 在运行runnable之前将检查上下文小部件。 如果仍然有效即未处置则将执行代码否则将静默删除该代码。 尽管忽略已处置小部件的代码的行为可能看起来很粗心但它适用于到目前为止我们遇到的所有情况。 进行线程间通信的单元测试代码特别难以测试。 因此尽管UIThreadSynchronizer是无状态的但必须对其进行实例化以使其可以通过test double替换。 带有相应测试的源代码可以在这里找到 https : //gist.github.com/rherrmann/7324823630a089217f46 尽管示例使用了asncExec但UIThreadSynchronizer也支持syncExec。 并且当然helper类也与RAP / RWT兼容。 如果您完整地阅读了源代码您可能已经注意到可能存在争用情况。 因为Widget类的所有方法都不是线程安全的所以isDisposed或getDisplay返回的值可能是陈旧的请参见第51 行和第60行 。 当时故意将其忽略-阅读我没有找到更好的解决方案。 尽管runnable可能会被错误地排入队列但是isDisposed-check在UI线程上执行将最终阻止代码执行。 剩下的线程问题还有另一个绝对是很小的机会恰好在调用asyncEecxec之前检查显示器的处置方式以免发生小部件处置异常。 但是如果将显示放置在检查和asyncExec的调用之间则可能会发生这种情况。 尽管可以通过将调用包装到忽略小部件处理的异常的try-catch块中来解决asyncExec的问题但对syncExec而言相同的方法将失败。 无法通过合理的努力将可运行对象引发的SWTException与syncExec引发的SWTException区别开来。 翻译自: https://www.javacodegeeks.com/2014/09/how-to-safely-use-swts-display-asyncexec.html