SwingWorker get()冻结接口

问题描述 投票:0回答:1

我正在使用SwingWorker在后台完成一些长时间运行的数据库调用。在执行SwingWorker之前,我启动了一个带有标签的jpanel,以通知用户该应用程序正在做一些后台工作。问题是,如果我使用SwingWorker get()方法获取长时间运行的操作的结果,我的jpanel将冻结,并且什么都不会显示。如果我不使用get()方法,则jpanel会正常显示。

您能告诉我我可能做错了什么吗?我已经花了几个小时在这上,却不知道为什么。在完成所有jpanel创建之后,SwingWorker将被执行,我不明白为什么它会挂起。

非常感谢!

创建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()时冻结:enter image description here

带有注释worker.get()代码块的函数:私人无效的快照OldVariables(){

    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的屏幕快照未冻结并正确显示:enter image description here

java jpanel swingworker
1个回答
0
投票

据我所知,除非您确定已完成处理,否则不应直接从UI线程调用SwingWorkerget()方法。相反,您应该在覆盖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();
    }
}

希望有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.