SwingWorker get() 冻结接口
SwingWorker get() freezing interface
我正在使用 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();
}
函数等待 worker.get(): 时 jpanel 冻结的屏幕截图
带有注释 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 */
}
jpanel 的屏幕截图未冻结且显示正确:
据我所知,您不应该直接从 UI 线程调用 SwingWorker
的 get()
方法,除非您确定它已完成处理。相反,您应该在 overriden MySwingWorker.done()
中调用它,您可以在其中确定后台任务已完成执行。
这无关紧要,所有 JPanel
创建都是在阻塞之前完成的,因为 Swing 仍然需要其主 UI 线程来重新绘制和更新 UI 并保持响应。通过调用 get()
您将阻止它。
从 UI 线程你应该只调用 execute()
并且所有结果处理(在你的情况下是 productIds = snap.getProductIds(); oldLocationIds = snap.getOldLocationIds(); oldStatusIds = snap.getOldStatusIds();
)应该在 done()
回调中完成。
this answer 中提供了一个简单示例。
在你的情况下应该是这样的:
//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();
}
}
希望对您有所帮助。
我正在使用 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();
}
函数等待 worker.get(): 时 jpanel 冻结的屏幕截图
带有注释 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 */
}
jpanel 的屏幕截图未冻结且显示正确:
据我所知,您不应该直接从 UI 线程调用 SwingWorker
的 get()
方法,除非您确定它已完成处理。相反,您应该在 overriden MySwingWorker.done()
中调用它,您可以在其中确定后台任务已完成执行。
这无关紧要,所有 JPanel
创建都是在阻塞之前完成的,因为 Swing 仍然需要其主 UI 线程来重新绘制和更新 UI 并保持响应。通过调用 get()
您将阻止它。
从 UI 线程你应该只调用 execute()
并且所有结果处理(在你的情况下是 productIds = snap.getProductIds(); oldLocationIds = snap.getOldLocationIds(); oldStatusIds = snap.getOldStatusIds();
)应该在 done()
回调中完成。
this answer 中提供了一个简单示例。
在你的情况下应该是这样的:
//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();
}
}
希望对您有所帮助。