我怎么知道,我是否应该在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
不确定这是最好的方法,还是有可靠的方法来解决?
答案 0 :(得分:1)
如果你真的需要一些超级通用的东西“调用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
}
您还可以在仅EDT方法中添加断言作为一种可执行文档:
assert SwingUtilities.isEventDispatchThread();
简而言之:如果您很难跟踪自己所处的线程,那么您的代码可能非常苛刻,以至于您很难跟踪任何内容,而您应该担心重构代码,而不是你正在上线。
答案 1 :(得分:0)
实际上
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配置应用以进行测试。如果UI相关代码在EDT之外运行,则抛出异常。
答案 2 :(得分:0)
几乎所有的Swing方法都需要在UI线程上执行。有一些例外(例如一些setMethods
)。这些异常记录在API文档中(通常称为“此方法是线程安全的”)。 然而,一般规则是所有 GUI更新应该在UI线程上进行。
在大多数情况下,你应该知道你当前在哪个线程。这很容易辨别。 GUI事件触发的所有回调都在UI线程上执行,主线程和您启动的所有其他线程中的操作不在UI线程上。
如果您有时会从自己的线程中调用代码,有时也会从UI线程调用代码,您可以像在问题中显示的那样,通过调用EventQueue.isDispatchThread()
来确定您是否在UI线程上
我会将代码放在一个单独的方法updateGuiComponent(...)
中执行
if (EventQueue.isDispatchThread())
updateGuiComponent(...);
else
SwingUtilities.invokeLater(new Runnable() { // or invokeAndWait
public void run() { updateGuiComponent(...); }
});