无效的线程访问:AWT ActionListener 中的 SWT

Posted

技术标签:

【中文标题】无效的线程访问:AWT ActionListener 中的 SWT【英文标题】:Invalid Thread Access: SWT in AWT ActionListener 【发布时间】:2018-04-11 18:54:14 【问题描述】:

试图摆脱这个 SWTException: Invalid thread access。从 JButton ActionListener 中生成。最终目的是让按钮打开浏览器窗口,导航到 URL,然后将 URL 带回打开对话框...

private static final Display display = Display.getDefault();

// Fired from JButton:
class ShowBrowserAction implements java.awt.event.ActionListener 

    @Override
    public void actionPerformed(ActionEvent e) 

        // Place-holder UI Update...
        display.asyncExec(new Runnable() 
            public void run() 
              System.out.println("Async task run");
            
        );

        // Blocking until UI element is done...
        while (!display.isDisposed()) 
           // Always gives a thread access error, but still calls async event:  
           if ( !display.readAndDispatch()  )
                display.sleep();
        

       

想法?

【问题讨论】:

我可以用 try/catch 包围 readAndDispatch ,它实际上似乎非常好。但这似乎是作弊,我想以后会回来困扰我。 看来,如果我将显示实例更改为 new Display() 而不是 Display.getDefault() 错误就会消失。但我不明白为什么会这样。 Display.getCurrent() 返回“null”,因此当前线程中似乎不存在活动显示...? 【参考方案1】:

您只能在 SWT UI 线程上调用 SWT 操作。不支持在其他任何地方调用它们。

如果您想等待可运行的 UI 完成,请使用 syncExec 而不是 asyncExec

您说它似乎有效,但这在不同平台上会有所不同。例如在 macOS 上它肯定会完全失败。

【讨论】:

但在上面的示例中,我实际上并没有调用任何 UI 操作,是吗? display.readAndDispatch 是唯一被调用的方法,这不是 UI 更新,对吧? Display 相关的任何操作都算作 UI 操作。 readAndDispatch 将执行所有待处理的 UI 操作,因此它必须在 UI 线程中运行。 asyncExecsyncExec 是唯一的例外。

以上是关于无效的线程访问:AWT ActionListener 中的 SWT的主要内容,如果未能解决你的问题,请参考以下文章

Java AWT - repaint()方法线程调度

《万年历》第3节:项目完整代码

线程间操作无效:从不是创建控件的线程访问它的三种方法

访问从不同线程访问的控件时如何处理无效的跨线程操作?

C# 委托 / 跨线程访问UI / 线程间操作无效: 从不是创建控件“Form1”的线程访问它

跨线程操作无效:控件“statusStrip”从创建它的线程以外的线程访问