java - 有什么区别吗?SwingWorker#publish vs SwingUtilities#invokeLater
问题描述
假设我们有一个必须在后台运行的长/繁重的任务,并将其进度或其他任何内容发布到 GUI。我知道这个发布必须发生在事件调度线程上。这就是我们将 aSwingWorker
用于任务的原因。
所以,我们所做的是这样的:
public class WorkerTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout());
JLabel label = new JLabel();
frame.add(label);
startWorker(label);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
});
}
private static void startWorker(JLabel label) {
new SwingWorker<Integer, Integer>() {
@Override
protected Integer doInBackground() throws Exception {
for (int i = 0; i < 500; i++) {
publish(i);
Thread.sleep(500); //Simulate long task
}
return null;
}
@Override
protected void process(List<Integer> chunks) {
Integer integer = chunks.get(0);
label.setText(String.valueOf(integer));
}
}.execute();
}
}
我的问题是,上述内容与此有何不同:
private static void startWorker(JLabel label) {
new SwingWorker<Integer, Integer>() {
@Override
protected Integer doInBackground() throws Exception {
for (int i = 0; i < 500; i++) {
int i2 = i;
SwingUtilities.invokeLater(() -> {
label.setText(String.valueOf(i2));
});
Thread.sleep(500); //Simulate long task
}
return null;
}
}.execute();
}
在这两种情况下,作为label.setText()
对 GUI 的更新,都会运行到事件调度线程。它们有何不同?
当然,问题还在于为什么我应该在方法结束时done()
对工作人员实施方法而不是调用?除了处理方法中可能抛出的异常。SwingUtilities.invokeLater
doInBackground
doInBackground
解决方案
查看类中的方法的javadoc。publish()
SwingWorker
因为流程方法是在事件调度线程上异步调用的,所以在流程方法执行之前可能会发生对发布方法的多次调用。出于性能目的,所有这些调用都合并为一个带有串联参数的调用。
SwingUtilities.invokeLater()
根据您问题中的代码,直接从方法调用doInBackground()
不会执行合并。也许您可以想到需要合并的原因?另请参阅具有中期结果的任务
关于done()
类中的方法SwingWorker
,你也问过,我再次推荐你参考javadoc
doInBackground 方法完成后在事件调度线程上执行。默认实现什么也不做。子类可以重写此方法以在事件调度线程上执行完成操作。请注意,您可以在此方法的实现内部查询状态,以确定此任务的结果或此任务是否已被取消。
所以你不必重写 method done()
。就个人而言,我通常向我的对象添加一个属性侦听器,以处理在 [ ] 任务完成后SwingWorker
我需要执行的任务。SwingWorker
但是,当然,YMMV。
推荐阅读
- python - 将 numpy uint8 数组转换为字符串
- swift - SwiftUI 多个 API 请求
- gitlab - GitLab CI 计划管道未在主服务器上运行
- scala - Scala String indexOf Character 从右侧
- ios - AgoraKit Agora.io `UICollectionViewCell` 中的`videoView`,重新加载问题
- python - POSTGRESQL 使用 Python 添加数据而不重复
- javascript - 如何强制 Node.js 在登录时不显示我的登录按钮并在注销时显示它
- javascript - 使用 FormData 多部分发布请求在节点 js 中上传文件
- ruby-on-rails - 有没有办法使用 Rails Active Storage 在 CSS 中设置背景图像?
- gps - rinex GNSS 可观察文件上的每一列是什么意思?