我有一个用Swing实现的UI。一个组件做了一些可能需要一些时间的工作,所以我使用SwingUtilities.invokeLater
。但是,我正在阅读一些旧代码,并在ActionListener
:
if (!SwingUtilities.isEventDispatchThread()) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// code X
}
});
} else {
// code X
}
我认为这是有道理的,因为它将code X
与EDT区分开来。但是,我发现它很容易出错,因为我已经使用了几次,而且两次都忘记了else
部分。
问题是:SwingUtilities.isEventDispatchThread()
检查是否必要?或者我可以假设我不在EDT中并且总是使用invokeLater
吗?
非常感谢。
答案 0 :(得分:14)
即使您在EDT上,稍后调用也没有问题,但它肯定会改变事件的时间,因此您必须确保在EDT时不依赖于此处的代码序列。话虽这么说,一种避免忘记else的简单方法是用实用程序方法包装调用:
public static void invokeInDispatchThreadIfNeeded(Runnable runnable) {
if (EventQueue.isDispatchThread()) {
runnable.run();
} else {
SwingUtilities.invokeLater(runnable);
}
}
这样你永远不会忘记else
。
另外,一般情况下,你的idom重复code x
是一个非常糟糕的主意,因为你后来可能会发现你必须修复或改进代码而你只能在一个地方修复它,留下一个bug另一个。
答案 1 :(得分:2)
我相信您的特定用例,检查isEventDispatchThread()
是不必要的。直接调用invokeLater()
不会创建新线程,因此不会造成性能损失。
答案 2 :(得分:0)
代码真的应该知道它是否在EDT上(如果这是相关的)。所以java.awt.EventQueue.isDispatchThread
应该留给断言。
答案 3 :(得分:0)
如果您的代码中有一个线程(A)由EDT启动,并且在该线程(A)中您有另一个线程(B)必须修改您的GUI,在这种情况下您必须使用invokeLater螺纹(B)。但是,如果GUI的修改是通过第一个线程(A)进行的,则不必使用invokeLater。