4

我有一个用 Swing 实现的 UI。一个组件做了一些可能需要一些时间的工作,所以我使用SwingUtilities.invokeLater. 但是,我正在阅读一些旧代码,并在以下位置找到了这个ActionListener

if (!SwingUtilities.isEventDispatchThread()) {
    SwingUtilities.invokeLater(new Runnable() {
         public void run() {
             // code X
         }
    });
} else {
   // code X
}

我认为这是有道理的,因为它与code XEDT 是分开的。但是,我发现它很容易出错,因为我已经使用了几次,而且两次都忘记了这个else零件。

问题是:SwingUtilities.isEventDispatchThread()检查是否必要?或者我可以假设我不在 EDT 中并且总是使用invokeLater

非常感谢。

4

4 回答 4

14

即使您在 EDT 上,稍后调用也可以,但是它肯定会改变事件的时间,因此您必须确保您在 EDT 上时不依赖于此处的代码顺序。话虽如此,避免忘记 else 的一种简单方法是将调用包装在实用方法中:

public static void invokeInDispatchThreadIfNeeded(Runnable runnable) {
    if (EventQueue.isDispatchThread()) {
        runnable.run();
    } else {
        SwingUtilities.invokeLater(runnable);
    }
}

这样你就永远不会忘记else.

此外,一般来说,在您的惯用语中重复code x是一个非常糟糕的主意,因为您稍后可能会发现您必须修复或改进该代码,并且您只会在一个地方进行,而在另一个地方留下错误。

于 2010-04-21T15:32:37.423 回答
2

相信对于您的特定用例,检查isEventDispatchThread()是不必要的。直接调用invokeLater()不会创建新线程,因此不会出现性能损失。

于 2010-04-21T15:11:53.253 回答
0

代码真的应该知道它是否在 EDT 上(如果相关的话)。所以java.awt.EventQueue.isDispatchThread应该留给断言。

于 2010-04-21T15:47:13.463 回答
0

简单地说,如果您的代码中有一个由 EDT 启动的线程(A),并且在该线程(A)中您有另一个线程(B)必须修改您的 GUI,在这种情况下,您必须在线程(B)上使用 invokeLater )。但是,如果您的 GUI 修改是由第一个线程 (A) 进行的,则无需使用 invokeLater。

于 2017-11-06T17:49:05.967 回答