使用Swing进度条进行多线程处理

时间:2015-05-28 22:52:32

标签: java multithreading swing concurrency progress-bar

如果在执行RMI连接期间如何使我的进度条响应,我的想法已经用完了,所以我决定向你寻求帮助。

以下是代码:

Thread performLogin = new Thread(new Runnable()
{

    @Override
    public void run()
    {
        LoginResult = TryLogin();
    }
});

performLogin.start();
WaiterFrame.setVisible(true);
SetProgressDialog();

try
{
    performLogin.join();
}
catch(InterruptedException exc)
{
    System.err.println(exc.getLocalizedMessage());
}

if (LoginResult)
{ ... }


WaiterFrame.setVisible(false);
this.dispose();

进度条没有响应 - 在执行performLogin线程时没有动画。我试图在另一个线程上运行进度条框架,但结果是相同的(以及使用Eventqueue.invokelater())。

3 个答案:

答案 0 :(得分:1)

如果你使用的是Java 8,你可以尝试这样的事情:

CompletableFuture<LoginResult> loginResult = CompletableFuture.supplyAsync(this::tryLogin);
WaiterFrame.setVisible(true);
setProgressDialog();
loginResult.thenAccept(lr -> {
   //do your thing 
   WaiterFrame.setVisible(false); 
})

“thenAccept”还有其他选项,具体取决于您需要做什么。 “thenAccept”只消耗未来的内容。

如果不能选择Java 8,可以使用Guava的ListenableFuture和Executors来完成同样的工作。

答案 1 :(得分:1)

可能的原因是performLogin.join();阻止了事件调度线程,使得UI没有响应。

使用Swing(和大多数GUI框架)要记住两件事;

  1. 它是单线程的,这意味着如果您因任何原因阻止了EDT,它将无法再处理新事件或执行重新绘制
  2. 它不是线程安全的,所以你永远不应该在EDT的上下文之外修改UI的状态。
  3. 您可以使用SwingWorker,它允许您在后台线程中运行长时间运行的进程,但提供了许多机制,您可以通过这些机制安全地将更新发送回EDT。

    有关详细信息,请参阅Worker Threads and SwingWorker;有关示例,请参阅Issues with SwingWorker and JProgressBar

答案 2 :(得分:0)

非常感谢MadProgrammer!使用SwingWorker时,进度条可以正常工作。如果有人在将来鼓励相同的问题,我会发布代码:

PerformLogin = new SwingWorker<Boolean, Object>()
{
    @Override
    protected Boolean doInBackground() throws Exception
    {
        LoginResult = TryLogin();
        if (LoginResult)
        {
            MainF = new MainFrame();
            MainF.Connection = DataEntry.TestConnection;
            MainF.prepareFormToShow();
        }
        return LoginResult;
    }

    @Override
    protected void done()
    {
        if (LoginResult == true)
        {
            EventQueue.invokeLater(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        MainF.setVisible(true);
                        WaiterFrame.setVisible(false);
                    }
                });
        }
        else
        {
            setVisible(true);
            this.cancel(true);
            JOptionPane.showMessageDialog(null, "Wrong adress!",
            "Błąd",JOptionPane.WARNING_MESSAGE);
        }
    }

WaiterFrame.setVisible(true);
PerformLogin.execute();

在主线程中