在New Thread中打开Eclipse Wizard或Eclipse MessageDialog

时间:2016-01-14 22:08:47

标签: java eclipse multithreading

我想在一个新线程中打开一个Eclipse WizardMessageDialog,但不知怎的,我总是得到一个像这样的例外:

Exception in thread "Thread-7" org.eclipse.swt.SWTException: Invalid thread access
    at org.eclipse.swt.SWT.error(SWT.java:4491)
    at org.eclipse.swt.SWT.error(SWT.java:4406)
    at org.eclipse.swt.SWT.error(SWT.java:4377)
    at org.eclipse.swt.widgets.Widget.error(Widget.java:482)
    at org.eclipse.swt.widgets.Shell.<init>(Shell.java:266)
    at org.eclipse.swt.widgets.Shell.<init>(Shell.java:362)
    at org.eclipse.jface.window.Window.createShell(Window.java:486)
    at org.eclipse.jface.window.Window.create(Window.java:429)
    at org.eclipse.jface.dialogs.Dialog.create(Dialog.java:1096)
    at org.eclipse.jface.window.Window.open(Window.java:792)
    at org.eclipse.jface.dialogs.MessageDialog.open(MessageDialog.java:330)
    at de.uka.ipd.sdq.beagle.gui.GuiController$DialogPolling.run(GuiController.java:126)
    at java.lang.Thread.run(Thread.java:745)

使用这样的代码时:

/**
 * Opens up the dialog displaying the actions "pause", "continue", and "abort" to the
 * user. These actions are regarding the analysis.
 */
private void engageDialog() {
    final String dialogTitle = "Beagle Analysis is Running";
    final String dialogMessage = "Beagle Analysis is running.";
    final String[] buttonLabels = {"Abort", "Pause"};
    this.messageDialog =
        new MessageDialog(this.shell, dialogTitle, null, dialogMessage, MessageDialog.INFORMATION, buttonLabels, 0);
    new Thread(new DialogPolling()).start();
}

private class DialogPolling implements Runnable {

    @Override
    public void run() {
        final int buttonClick = GuiController.this.messageDialog.open(); // line 126

        if (buttonClick == 0) {
            System.out.println("User clicked 'Abort'.");
        }

        if (buttonClick == 1) {
            System.out.println("User clicked 'Pause'.");
        }
    }
}

这是来自GuiController,标有第126行。如果看不到行号,请向右滚动。

如何在新线程中打开向导或MessageDialog?

2 个答案:

答案 0 :(得分:0)

所有向导,对话框,......必须在单个SWT UI线程中打开。您可以在另一个线程中使用Display.syncExec调用来在UI线程中运行打开的对话框。

Display.getDefault().syncExec(runnable);

您的Runnable可以调用对话框open并将buttonClick值保存在syncExec返回时您可以访问的位置。

答案 1 :(得分:0)

GUI系统通常设计为单线程,因为它几乎不可能编写多线程GUI系统。有许多用户交互和太多事件。

这就是为什么GUI框架通常会创建自己的专用线程,并且所有GUI活动都在此线程中。例如,Swing有自己的AWT线程。如果在该线程中执行长时间运行操作,则会导致程序冻结(程序不会对用户输入做出反应)。如果要避免这种情况,必须在不同的线程中运行逻辑。但只有你的逻辑,而不是GUI动作!

有一些有用的类可以解决这个问题 - 例如 SwingWorked ,它设计用于在后台线程中运行冗长的GUI交互任务