【问题标题】:How to synchronise code with the UI Thread in Standard Widget Toolkit如何在 Standard Widget Toolkit 中将代码与 UI 线程同步
【发布时间】:2026-01-11 13:40:01
【问题描述】:

当我尝试运行我的代码时,我不断收到一个 SWTException,上面写着“无效的线程访问”。我读了,问题似乎是有代码试图从 UI 线程外部访问 SWT 对象。具体来说,我有一个表格小部件,并且添加了一个选择侦听器。这是选择监听器的代码。

rosterTable.addSelectionListener(new SelectionAdapter()

    {
        public void widgetSelected(final SelectionEvent event)
        {

              createChat(connection,event);


        }

            });

这里是 createChat 方法的代码:

public void createChat(final XMPPConnection connection,final SelectionEvent event)
{
    Display.getDefault().syncExec(new Runnable()        
    {
        public void run()
        {
            String s = event.item.toString();
            int length = event.item.toString().length();
            ClassView cv = new ClassView(connection,s.substring(11,length -1),null);
        }
    });

As you can see I've tried too synchronise the code which is outside the UI thread, with the UI thread by wrapping it in the syncExec method but I still get the exception when the table item is selected which leads me to believe我把 syncExec 部分放在了错误的地方。

我还认为问题可能来自 createChat 方法中实例化的 ClassView 对象使用 SWT 小部件,但我不确定。

有人知道syncExec 代码应该放在哪里吗?

或者如果我做错了,我该如何解决?

更新:

我按照你说的做了,不幸的是我仍然遇到异常,我对代码进行了一些重新设计,所以现在看起来有点不同,我认为这不会有任何区别,但以防万一再次监听器的代码:

 rosterTable.addSelectionListener(new SelectionAdapter()

    {
        public void widgetSelected(final SelectionEvent event)
        {

           selectedUser = event.item.toString();
           System.out.println(selectedUser);
           rm.createChat(selectedUser);

        }






    });

这是现在在不同类中的方法的代码:

public void createChat(String item)
{
    int length = item.length();
    Chatter c = new Chatter(connection,item.substring(11,length-1));

}

这是异常的堆栈跟踪:

org.eclipse.swt.SWTException: Invalid thread access
at org.eclipse.swt.SWT.error(SWT.java:3884)
at org.eclipse.swt.SWT.error(SWT.java:3799)
at org.eclipse.swt.SWT.error(SWT.java:3770)
at org.eclipse.swt.widgets.Display.checkDisplay(Display.java:721)
at org.eclipse.swt.widgets.Display.create(Display.java:783)
at org.eclipse.swt.graphics.Device.<init>(Device.java:135)
at org.eclipse.swt.widgets.Display.<init>(Display.java:454)
at org.eclipse.swt.widgets.Display.<init>(Display.java:445)
at instantmessengerplugin.ClassView.<init>(ClassView.java:33)
at instantmessengerplugin.Chatter.<init>(Chatter.java:20)
at instantmessengerplugin.RosterManager.createChat(RosterManager.java:48)
at instantmessengerplugin.RosterView$1.widgetSelected(RosterView.java:103)
at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:228)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1003)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3880)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3473)
at instantmessengerplugin.RosterView.<init>(RosterView.java:158)
at instantmessengerplugin.Connection.connect(Connection.java:110)
at instantmessengerplugin.Connection$1.widgetSelected(Connection.java:65)
at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:228)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1003)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3880)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3473)
at instantmessengerplugin.Connection.<init>(Connection.java:77)
at instantmessengerplugin.Connection.main(Connection.java:119)

【问题讨论】:

    标签: java swt


    【解决方案1】:

    您从 UI 线程中调用 syncExec(),这绝对是个问题。

    所有 SWT 事件都在 UIThread 上触发,因此当您从 widgetSelected() 中调用 createChat() 时,您已经在 UIThread 上。在createChat() 中,您尝试再次阻塞 UIThread,这会导致问题。

    尝试拨打syncExec() 并报告发生的情况。如果您仍然遇到异常,请包含堆栈跟踪。

    如果您正在创建一个简单的 SWT 程序,通常您不必担心 UI 线程,因为大多数简单的应用程序都会响应事件而工作,在 UI 线程上处理业务逻辑也是如此。当您开始生成线程(或使用诸如 java.util.concurrent 之类的东西在幕后为您处理线程)时,您必须开始担心 UI 线程,以使您的 ui 更具响应性。

    【讨论】:

    • 您展示了 createChat() 的代码,但根据堆栈跟踪,异常实际上发生在 Chatter 中的构造函数调用的 ClassView 的构造函数中。你能在这两个类中发布一些相关代码吗?我们会追查到这一点。
    【解决方案2】:

    我解决了这个问题。例外是因为在 ClassView 中我试图创建一个 SWT Display 类的实例,而此时已经存在它的另一个实例。该平台只允许一个人在任何时候打开。

    我已经更改了代码,以便只使用一个显示器并且异常消失了。

    感谢您的所有帮助。

    【讨论】: