java - SwingWorker get() 冻结接口
问题描述
我正在使用 SwingWorker 在后台完成一些长时间运行的数据库调用。在执行 SwingWorker 之前,我启动了一个带有标签的 jpanel,以通知用户该应用程序正在执行一些后台工作。问题是,如果我使用 SwingWorker get() 方法来获取长时间运行的操作的结果,我的 jpanel 会冻结并且什么都不会显示。如果我不使用 get() 方法,jpanel 会正常显示。
你能告诉我我可能做错了什么吗?我已经花了几个小时没有弄清楚为什么。SwingWorker 在所有 jpanel 创建完成后被执行,我不明白它为什么会挂起。
非常感谢!
创建 jpanel 并启动 SwingWorker 的函数:
private void snapshotOldVariables() {
JFrame loadingJFrame = new JFrame();
LoadingJPanel loadingJPanel = new LoadingJPanel();
Dimension d1 = new Dimension();
d1.setSize(500, 500);
loadingJFrame.setResizable(false);
loadingJFrame.setMinimumSize(d1);
loadingJFrame.setTitle("Loading...");
loadingJFrame.setLocationRelativeTo(null);
loadingJFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
loadingJFrame.add(loadingJPanel);
loadingJFrame.setVisible(true);
loadingJPanel.updateStatus("Creating snapshot of values...");
MySwingWorker worker = new MySwingWorker(tableRows, selectedItems);
worker.execute();
GMSnapshotVO snap = null;
try {
snap = worker.get();
} catch (InterruptedException | ExecutionException e) {
System.out.println(e);
}
loadingJPanel.updateStatus("Complete");
loadingJFrame.dispose();
productIds = snap.getProductIds();
oldLocationIds = snap.getOldLocationIds();
oldStatusIds = snap.getOldStatusIds();
}
jpanel 的屏幕截图在函数等待 worker.get() 时冻结:
带有注释 worker.get() 代码块的函数: private void snapshotOldVariables() {
JFrame loadingJFrame = new JFrame();
LoadingJPanel loadingJPanel = new LoadingJPanel();
Dimension d1 = new Dimension();
d1.setSize(500, 500);
loadingJFrame.setResizable(false);
loadingJFrame.setMinimumSize(d1);
loadingJFrame.setTitle("Loading...");
loadingJFrame.setLocationRelativeTo(null);
loadingJFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
loadingJFrame.add(loadingJPanel);
loadingJFrame.setVisible(true);
loadingJPanel.updateStatus("Creating snapshot of values...");
MySwingWorker worker = new MySwingWorker(tableRows, selectedItems);
worker.execute();
/* COMMENT STARTS HERE
GMSnapshotVO snap = null;
try {
snap = worker.get();
} catch (InterruptedException | ExecutionException e) {
System.out.println(e);
}
loadingJPanel.updateStatus("Complete");
loadingJFrame.dispose();
productIds = snap.getProductIds();
oldLocationIds = snap.getOldLocationIds();
oldStatusIds = snap.getOldStatusIds();
COMMENT ENDS HERE */
}
解决方案
据我所知,除非您确定它已完成处理,否则不应直接从 UI 线程调用SwingWorker
'方法。get()
相反,您应该在 overriden 中调用它MySwingWorker.done()
,您可以确保后台任务已完成执行。
无关紧要的是,所有JPanel
创建都在阻塞之前完成,因为 Swing 仍然需要其主 UI 线程来重新绘制和更新 UI 并保持响应。通过调用get()
你正在阻止它。
您应该从 UI 线程调用execute()
并且所有结果处理(productIds = snap.getProductIds(); oldLocationIds = snap.getOldLocationIds(); oldStatusIds = snap.getOldStatusIds();
在您的情况下)都应该在done()
回调中完成。
这个答案中有一个简单的例子。
在你的情况下,它应该是这样的:
//inside MySwingWorker
@Override
protected void done() {
try {
System.out.println("My long running database process is done. Now I can update UI without blocking/freezing it.");
GMSnapshotVO snap = get();
loadingJPanel.updateStatus("Complete");
loadingJFrame.dispose();
productIds = snap.getProductIds();
oldLocationIds = snap.getOldLocationIds();
oldStatusIds = snap.getOldStatusIds();
//..do other stuff with ids
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
希望能帮助到你。
推荐阅读
- excel - 用作绘图参考时,索引函数不起作用
- google-chrome - 不支持直通,gl 在使用 chromium 驱动程序 91 运行 salenium 项目时被禁用 ..plz 帮助它
- google-apps-script - 按 ID 将指定值从 CSV 导入 Google 工作表
- wordpress - 如何在 WooCommerce 中定义基于支付网关的每个产品的自定义价格?
- jupyter-notebook - AWS Sagemaker 笔记本间歇性“无法找到凭证”
- html - 使用引导程序 4 时字体机器人不起作用
- javascript - Npm publish 给出了无效的目录
- mongodb - MongoDB 查询以查找同时拥有 SELL 和 PURCHASE 的客户列表
- msbuild - nuget restore 未在 AWS CodeBuild windows 默认映像中创建 xml 文件
- python - TypeError:使用 MTCNN 时,元组索引必须是整数或切片,而不是 str