我有一个 Eclipse rcp 应用程序。当这个命令正在执行时,我有一个命令。我需要启动一个线程。执行此线程后,必须更新 GUI。但我想这个线程或其他非 SWT 线程无法更新 GUI。但这似乎是合理的。当我试图这样做时,我得到了Exception in thread "Thread-5" org.eclipse.swt.SWTException: Invalid thread access
. 我怎样才能实现这个目标?
6 回答
使用 SWT,您需要在主线程上完成任何更新 GUI 的操作,或者在 Eclipse 中,它被称为 UI 线程(它是同一个线程)。您收到此错误是因为您试图访问另一个线程上的 SWT 对象。考虑使用Display.syncExec()
或Display.asyncExec()
将 SWT 相关处理移至主线程。你要小心syncExec()
不要导致死锁。
通常我不会在 RCP 应用程序中使用 java.lang.Thread,因为 Eclipse 通过 Jobs API ( https://eclipse.org/articles/Article-Concurrency/jobs-api提供了不同级别的抽象和对长时间运行的操作的控制.html)。这是您的问题的解决方案:
Runnable uiUpdater = new Runnable() {
public void run() {
// update SWT UI safely here
// ...
}
};
Job longRunningOperation = new Job("My command") {
protected IStatus run(IProgressMonitor monitor) {
// some time consuming code here
// ...
Display.getDefault().asyncExec(uiUpdater);
return Status.OK_STATUS;
}
};
longRunningOperation.schedule();
根据您需要在后台执行的操作,您可能希望查看 Eclipse Jobs API,它为运行后台任务和向用户提供反馈提供支持。搜索“eclipse 工作教程”;这是一个很好的:http ://www.vogella.com/articles/EclipseJobs/article.html
你得到了这个感觉,因为你试图从非 UI 线程访问 UI 线程。使用Display.syncExec()
orDisplay.asyncExec()
将解决您的问题。
您正面临 SWT 世界中最常见的异常!无效的线程访问仅意味着一件事:您想要修改或只是访问 GUI 元素,并且您在不是 GUI 线程的线程中进行操作。
当您的代码点击按钮或类似的东西时,它永远不会发生,但是,当您使用后台进程或异步通知时,它会一直发生。
有一个解决方案:在特定块中执行您的代码:
Display.getDefautl().syncExec(new Runnable() {
public void run() {
// code related to GUI element(s)
}
}
或者
Display.getDefautl().asyncExec(new Runnable() {
public void run() {
// code related to GUI element(s)
}
}
在第一种情况下,执行是同步的。调用线程等待 run 方法被执行。在第二种情况下,调用线程没有等待。
要了解有关 Eclipse 应用程序中线程的更多信息,请查看 Debug 视图中的堆栈(在调试模式下)。第一个称为Main的线程是 UI 线程。
您应该使用 Display.getDefault().asyncExec() 或 Display.getDefautl().syncExec()。
示例代码:
@PostConstruct
public void createControls(Composite parent) {
.... \\ label definition
}
public void updateInterface(String message)
{
try{
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
try{
label.setText(message);
}
catch(Exception exc){
System.out.println(exc);
}
}
});
}
catch(Exception exception){
System.out.println(exception);
}
}