代码之家  ›  专栏  ›  技术社区  ›  Cheok Yan Cheng

如何确定何时在GUI线程中进行函数调用

  •  1
  • Cheok Yan Cheng  · 技术社区  · 15 年前

    我怎么知道,我是否应该在GUI线程内进行函数调用。

    if (SwingUtilities.isEventDispatchThread()) {
        // ...
    } else {
    
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                // ...
            }
        });
    }
    

    // Should I call this within GUI thread?
    jTable.getModel().setValueAt(...
    

    或者

    // Should I call this within GUI thread?
    jComboBox.showPopup();
    

    据我所知,在不正确的线程中进行操作,可能会产生不易发现的问题。因此,我很难核实我是否做了正确的事情。

    目前,我所做的是, If I am not sure, I will just call them in GUI thread

    不确定这是最好的方法,还是有可靠的方法来解决?

    3 回复  |  直到 15 年前
        1
  •  1
  •   gustafc    15 年前

    如果您真的需要一些超通用的“调用ASAP”功能,那么像这样的助手很有用:

    void invokeAsSoonAsPossible(Runnable action) {
        if (SwingUtilities.isEventDispatchThread())
            action.run();
        else SwingUtilities.invokeLater(action);
    }
    
    // Usage:
    invokeAsSoonAsPossible(new Runnable(){
        @Override
        public void run() {
            jTable.getModel().setValueAt(...
        }
    });
    

    但我的经验告诉我,这是一个更好的策略来组织和记录你的代码,这样就更容易跟踪在哪里运行的代码。如果类中有一个公共方法应该在EDT上运行,JavaDoc是一个好朋友:

    /**
     * Blah blah blah, describe the method's purpose.
     * <p>
     * <strong>Note:</strong> This method should always be 
     * invoked on the Swing event dispatch thread.
     */
    public Pony calulateValue() {
        // go ahead and touch the components any way you please
    }
    

    assert SwingUtilities.isEventDispatchThread();
    

    简而言之:如果你很难跟踪你在哪个线程,那么你的代码可能太粗糙了,以至于你很难跟踪任何东西,你应该担心重构你的代码,而不是你在哪个线程上。

        2
  •  0
  •   Boris Pavlović    15 年前

    事实上

    if (SwingUtilities.isEventDispatchThread()) {
      // just do it, you're already in EDT
    } else {
      SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            // ...
        }
      });
    }
    

    所有涉及Swing或AWT组件/类的代码都应该在EDT中运行,即使用 SwingUtilities.invokeLater(Runnable) 帮手。

    您可以使用 Substance Look&Feel

        3
  •  0
  •   aioobe    15 年前

    几乎所有的Swing方法都需要在UI线程上执行。有一些例外(例如 setMethods ). 这些异常记录在API文档中(通常说“这个方法是线程安全的”)。 全部的


    在大多数情况下 应该 知道你现在在哪条线上。这很容易说出来。由GUI事件触发的所有回调都在UI线程上执行,主线程和所有其他已启动的线程中的操作都不在UI线程上。

    但是,如果您确实有时从自己的线程调用代码,有时从UI线程调用代码,您可以通过调用 EventQueue.isDispatchThread()

    我会把要执行的代码放在一个单独的方法中, updateGuiComponent(...) 并且做

    if (EventQueue.isDispatchThread())
        updateGuiComponent(...);
    else
        SwingUtilities.invokeLater(new Runnable() {          // or invokeAndWait
            public void run() { updateGuiComponent(...); }
        });