web-dev-qa-db-ja.com

Java SWTによる無効なスレッドアクセスエラー

シンプルなJava SWTアプリJavaこれまでのところ、奇妙なことは、発生したイベントを聞いてメッセージボックス/アラートボックスを起動しようとするときです自分のクラスの1つで、「無効なスレッドアクセス」というエラーが表示されます。

クラスイベントが発生し、メインクラスによって聞こえますが、「無効なスレッドアクセス」エラーが表示されるのは、メッセージボックスを表示する必要があるときです。 SWT GUIを作成する他のすべてのコードで構成される関数でMessageBoxを表示しようとしています。これは、関数がどのように見えるかです:

public void createContents() {
    Shell shell = new Shell();
    //.....all the SWT GUI codes....
    MessageBox msg = new MessageBox(Shell, SWT.OK);
    myClass.addEventListener(new MyClassEventClassListener() {
        @Override
        public void myClassEventHandler(MyClassEvent e) {
            msg.setText("Hello");
            msg.setMessage("Event fired!");
            int result = msg.open();
        }
    });
}

これらは、クラス内の補助機能です。

<!-- language: lang-Java -->
protected static Shell shell;
public static void main(String[] args) {
    MyClass new myClass = new MyClass();

    try {
        SWTApp window = new SWTApp();
        window.open();
    } catch (Exception e) {     
}

public void open() {
    Display display = Display.getDefault();
    createContents();
    Shell.open();
    Shell.layout();
    while (!Shell.isDisposed()) {
        if (!display.readAndDispatch()) {
            display.sleep();
        }
    }
}

エラースタックトレースは次のとおりです。

Exception in thread "AWT-EventQueue-0" org.Eclipse.swt.SWTException: Invalid thread access
    at org.Eclipse.swt.SWT.error(SWT.Java:4083)
    at org.Eclipse.swt.SWT.error(SWT.Java:3998)
    at org.Eclipse.swt.SWT.error(SWT.Java:3969)
    at org.Eclipse.swt.widgets.Display.error(Display.Java:1249)
    at org.Eclipse.swt.widgets.Display.checkDevice(Display.Java:755)
    at org.Eclipse.swt.widgets.Display.getShells(Display.Java:2171)
    at org.Eclipse.swt.widgets.Display.setModalDialog(Display.Java:4463)
    at org.Eclipse.swt.widgets.MessageBox.open(MessageBox.Java:200)

どんな助けも素晴らしいでしょう。ありがとう!

27
Carven

これは、リスナーコードがSWT Displayスレッドの外部から呼び出されるためにスローされます。次のように表示スレッドでコードを実行します。

Display.getDefault().syncExec(new Runnable() {
    public void run() {
        // ...
    }
});

または、非同期的に:

Display.getDefault().asyncExec(new Runnable() {
    public void run() {
        // ...
    }
});
74
5
Diogo