当我尝试运行我的代码时,我不断收到一个说“无效线程访问”的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);
}
});
正如你所看到的那样,我已经尝试过将UI线程之外的代码同步到UI线程,将它包装在syncExec方法中,但是当选择表项时我仍然得到异常,这让我相信我把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)
答案 0 :(得分:0)
您正在从UI线程中调用syncExec()
,这绝对是一个问题。
所有SWT事件都会在UIThread上触发,因此当您从createChat()
内拨打widgetSelected()
时,您已经在UIThread上。在createChat()
之内,您将再次尝试阻止UIThread导致问题。
尝试取消对此syncExec()
的调用,并报告正在发生的事情。如果仍有异常,请包括堆栈跟踪。
如果您正在创建一个简单的SWT程序,通常您不必担心UI线程,因为大多数简单的应用程序都可以响应事件而工作,因此在UI线程上处理业务逻辑。当你开始产生线程时(或者使用java.util.concurrent之类的东西,在幕后为你设置线程),你必须开始担心UI线程,以便让你的ui更具响应性。
答案 1 :(得分:0)
我解决了这个问题。异常来自这样一个事实:在ClassView中我试图创建类SWT显示的实例,当时已经存在另一个实例。该平台只允许任何一个人打开。
我更改了代码,因此只使用了一个显示,异常消失了。
感谢您的帮助。