【发布时间】:2016-10-05 16:12:33
【问题描述】:
您好,我一直在尝试学习如何使用 SwingWorker 来更新 Swing 应用程序的 GUI。
我的问题是:如果我有 2 个可以同时运行的 swingworker(每个都从不同的按钮触发)如何确保在 EDT 中以相同的顺序调用他们的 done 方法(以更新 gui)他们被解雇了?
我的观察和想法: 我试图将他们的 doInBackground() 方法与锁同步,以确保一个必须等待另一个完成任务才能继续。问题是我已经能够(仅几次)看到 swingworker_1 完成 doInBackground() (而第二个工人正在同步块中等待),但是 Swingworker_2 的 done 方法能够被 EDT 调用在 swingworker_1 的 done 方法之前,即使 swingworker_2 之后完成。我考虑在 doInBackground() 返回之前使用发布,这似乎总是有效,但可能是一种不好的做法,因为它似乎用于中间结果而不是最终结果?另一种可能性是在 doInBackground() 中使用 SwingUtilities.invokeLater 在返回之前更新 gui,我担心这也可能是一个不好的做法。提前致谢。
我使用的测试,按下第一个按钮,然后立即按下第二个按钮:
//Code that runs in the first button
SwingWorker<Void, Void> swingworker = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
synchronized (lock) {
System.out.println("Thread 1");
Thread.sleep(1000);
return null;
}
}
@Override
protected void done() {
System.out.println("Done with thread 1 ");
//update GUI
}
};
swingworker.execute();
//Code that runs in the second button
SwingWorker<Void, Void> swingworker = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
synchronized (lock) {
System.out.println("Thread 2");
return null;
}
}
@Override
protected void done() {
System.out.println("Done with thread 2 ");
//update GUI
}
};
swingworker.execute();
更新:只是为了澄清我不关心谁先开始(swingworker_1 或 swingworker_2),这取决于首先按下哪个按钮。我要保证的是,如果来自按钮的工作人员是第一个执行的(并因此在工作人员在 doInBackground() 方法中同步时完成),那么它也应该是第一个加入队列以更新 EDT 中的 gui .我发现即使工作人员被同步,这也不一定会发生,有时稍后启动任务的工作人员仍然设法在第一个之前更新 gui。
【问题讨论】:
-
我想知道您是否在描述一个 XY 问题,并要求您提供更多信息:首先,为什么这个顺序如此重要?这些工人在做什么,你的项目在做什么?
-
我自己,我尽量避免使用
done()方法,而是通常使用PropertyChangeListeners 监听worker 的状态变化。这减轻了 SwingWorker 必须进行任何特定于 GUI 的调用的责任,甚至可以了解 GUI 或任何调用代码。 -
我在您的代码中没有看到任何东西可以确保第一个工作人员在第二个工作人员之前获得
lock的监视器。 -
你好气垫船,想法是使用第一个 swingworker/按钮来启动后台数据,完成后它会将标签或其他内容更新为“在线”。第二个按钮可用于关闭,它将负责终止所有后台线程,完成后它将标签更新为离线。
-
你好 John,我们的想法不是确保一个在另一个之前运行,而是当一个 swingworker 运行时它会在另一个之前更新 gui,所以如果在第二个按钮被按下之前它应该更新gui 在按钮 1 之前,反之亦然。
标签: java swing concurrency swingworker