4

我有一个 Eclipse rcp 应用程序。当这个命令正在执行时,我有一个命令。我需要启动一个线程。执行此线程后,必须更新 GUI。但我想这个线程或其他非 SWT 线程无法更新 GUI。但这似乎是合理的。当我试图这样做时,我得到了Exception in thread "Thread-5" org.eclipse.swt.SWTException: Invalid thread access. 我怎样才能实现这个目标?

4

6 回答 6

6

使用 SWT,您需要在主线程上完成任何更新 GUI 的操作,或者在 Eclipse 中,它被称为 UI 线程(它是同一个线程)。您收到此错误是因为您试图访问另一个线程上的 SWT 对象。考虑使用Display.syncExec()Display.asyncExec()将 SWT 相关处理移至主线程。你要小心syncExec()不要导致死锁。

于 2012-05-16T15:19:10.290 回答
2

通常我不会在 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();
于 2016-07-01T05:29:02.873 回答
1

根据您需要在后台执行的操作,您可能希望查看 Eclipse Jobs API,它为运行后台任务和向用户提供反馈提供支持。搜索“eclipse 工作教程”;这是一个很好的:http ://www.vogella.com/articles/EclipseJobs/article.html

于 2012-05-16T16:41:52.427 回答
1

你得到了这个感觉,因为你试图从非 UI 线程访问 UI 线程。使用Display.syncExec()orDisplay.asyncExec()将解决您的问题。

于 2013-03-17T21:58:27.893 回答
0

您正面临 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 线程。

于 2015-06-18T22:03:22.850 回答
0

您应该使用 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);
        }   
    }
于 2016-04-01T20:51:26.320 回答