问题:我需要3个帖子。如果此值发生更改,Thread1将读取int值并启动操作(涉及UI)。 Thread2是UI。 Thread3是Thread1注意到int更改时应执行的操作。现在,当我启动thread2然后执行
display.async(new Thread1())
它将不会显示UI,因为稍后会调用open() - 方法。当我先打开()然后再显示display.async()时,它会立即抛出一个SWTException:
Exception in thread "Thread-0" org.eclipse.swt.SWTException: Failed to execute runnable (org.eclipse.swt.SWTException: Invalid thread access)
at org.eclipse.swt.SWT.error(Unknown Source)
at org.eclipse.swt.SWT.error(Unknown Source)
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Unknown Source)
at org.eclipse.swt.widgets.Display.runAsyncMessages(Unknown Source)
at org.eclipse.swt.widgets.Display.readAndDispatch(Unknown Source)
at sokobangui.SokobanGUIManager.run(SokobanGUIManager.java:57)
at java.lang.Thread.run(Unknown Source)
Caused by: org.eclipse.swt.SWTException: Invalid thread access
at org.eclipse.swt.SWT.error(Unknown Source)
at org.eclipse.swt.SWT.error(Unknown Source)
at org.eclipse.swt.SWT.error(Unknown Source)
at org.eclipse.swt.widgets.Display.checkDisplay(Unknown Source)
at org.eclipse.swt.widgets.Display.create(Unknown Source)
at org.eclipse.swt.graphics.Device.(Unknown Source)
at org.eclipse.swt.widgets.Display.(Unknown Source)
at org.eclipse.swt.widgets.Display.(Unknown Source)
at sokobangui.SokobanGUIManager.run(SokobanGUIManager.java:35)
at java.lang.Thread.run(Unknown Source)
at org.eclipse.swt.widgets.RunnableLock.run(Unknown Source)
... 5 more
当我单独启动thread1和thread2而不尝试同步它时,它工作正常,直到我尝试使用thread2初始化thread3。然后我得到这个:
Exception in thread "Thread-1" org.eclipse.swt.SWTException: Invalid thread access
at org.eclipse.swt.SWT.error(Unknown Source)
at org.eclipse.swt.SWT.error(Unknown Source)
at org.eclipse.swt.SWT.error(Unknown Source)
at org.eclipse.swt.widgets.Widget.error(Unknown Source)
at org.eclipse.swt.widgets.Widget.checkWidget(Unknown Source)
at org.eclipse.swt.widgets.Control.getShell(Unknown Source)
at sokobangui.GUICoordinator.switchToRoboControl(GUICoordinator.java:120)
at sokobangui.GUIListener.run(GUIListener.java:15)
at java.lang.Thread.run(Unknown Source)
所以,如果我被问到这里发生了什么,我会说同步线程存在一些问题,因为据我所知,显示线程需要“知道”哪些线程会修改表面。但是我不知道如何解决这个问题...
以下是一些代码片段:(thread1 = GUIListener; thread2 = SokobanGUIManager; thread3 = SwitchToRoboControl)
public class StartSokobanSolver {
public static void main(String[] args) {
GUIStatus.status = GUIStatus.MAIN;
Thread manager = new Thread(new SokobanGUIManager());
manager.start();
//Thread listener = new Thread(new GUIListener());
//listener.start();
}
}
public class SokobanGUIManager implements Runnable {
public void run() {
this.display = new Display();
this.display.asyncExec(new Thread(new GUIListener()));
this.shell = new Shell(this.display);
goToMainMenu();
this.shell.open();
while (!this.shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
GUIStatus.status = GUIStatus.END;
}
}
public class GUIListener implements Runnable {
private static GUICoordinator connector;
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
//try{
while(GUIStatus.status != GUIStatus.END) {
System.out.println("GUI-Status: " + GUIStatus.status);
if(GUIStatus.status == GUIStatus.INGAME_ROBOT) {
System.out.println("InGameRobot Start");
connector.switchToRoboControl();
System.out.println("InGameRobot End");
GUIStatus.status = GUIStatus.INGAME_SOLVED;
connector.isSolved();
} else {
System.out.println("Else");
try{ Thread.sleep(5000); } catch(Exception e) {}
}
if(GUIStatus.status == GUIStatus.END) {
Thread.currentThread().interrupt();
}
}
/*} catch(Exception e) {
System.out.println("Ende des Threads : " + e.toString());
Thread.currentThread().interrupt();
Not in the code atm to get the full exception message!
}*/
}
}
protected static void setCoordinator(GUICoordinator c) {
connector = c;
}
}
public class GUICoordinator {
...
protected void switchToRoboControl() {
if(this.roboControl != null) {
Solution solution = new Solution("1u:1l:1d");
Thread roco = new Thread(new SwitchToRoboControl(this.map, this, this.mapArea.getShell(), solution));
Display.getDefault().asyncExec(roco);
roco.start();
System.out.println("Thread started");
} else {
System.out.println("Epic fail");
}
}
}
public class SwitchToRoboControl implements Runnable {
...
public SwitchToRoboControl(Map map, GUICoordinator gui, Shell shell, Solution solution) {
this.map = map;
this.gui = gui;
this.shell = shell;
this.solution = solution;
}
@Override
public void run() {
...action to be performed
}
}
答案 0 :(得分:0)
根本不要启动GUIListener。使用菜单监听器"通过机器人解决谜语"这将安排游戏解决,然后执行一些UI操作。这可以通过两种方式实现:
1)直接通过机器人解决游戏问题"听者
2)启动计算解决方案的线程,然后使用" Display.asyncExcec" (或syncExec)在UI中显示解决方案
请参阅here如何将监听器附加到MenuItem。
希望有所帮助。