关于尝试异步(Thread)显示的SWTException

时间:2014-07-20 11:04:06

标签: java multithreading exception swt

问题:我需要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
        }
    }

1 个答案:

答案 0 :(得分:0)

根本不要启动GUIListener。使用菜单监听器"通过机器人解决谜语"这将安排游戏解决,然后执行一些UI操作。这可以通过两种方式实现:

1)直接通过机器人解决游戏问题"听者

2)启动计算解决方案的线程,然后使用" Display.asyncExcec" (或syncExec)在UI中显示解决方案

请参阅here如何将监听器附加到MenuItem。

希望有所帮助。