How do I wait for a SwingWorker's doInBackgrou

2020-02-05 12:22发布

Say I have the following code:

import java.lang.InterruptedException;
import javax.swing.SwingWorker;

public class Test
{
    private JDialog window;

    public Test
    {
        // instantiate window
    }

    private class Task extends SwingWorker<Void, Void>
    {
        public Void doInBackground()
        {
            try { Thread.currentThread().sleep(5000); }
            catch(InterruptedException e) {}
            return null;
        }
    }

    public void doTask()
    {
        Task task = new Task();
        task.execute();
    }

    protected void process()
    {
        // update various GUI components here
    }

    public static void main(String args[])
    {
        Test t = new Test();
        t.doTask();
        System.out.println("done");
    }
}

I need to wait until t.doTask() is done before printing out 'done', but I'm not sure exactly how. I know I should probably use join() here, but I need a thread to call it on, and I don't know how to get doInBackground()'s thread from where I need to call join(). Thanks for any help.


EDIT: Thanks for the responses. Unfortunately, get() and the like don't quite solve the problem. In my actual code, the SwingWorker also has an overridden process() function that updates a GUI window while the background thread is running. get() does stop 'done' from being printed till after doInBackground, but then the GUI doesn't update. I updated my sample code to reflect this, although now of course it won't compile.

Is there a way to get 'done' to print only once doInBackground is finished? Are the GUI update code and the 'done' statement on the same thread? Do I need to make a new thread?

4条回答
你好瞎i
2楼-- · 2020-02-05 12:58

You can override the done() method, which is called when the doInBackground() is complete. The done() method is called on EDT. So something like:

@Override
protected void done() {
  try {
    super.get();

    System.out.println("done");
    //can call other gui update code here
  } catch (Throwable t) {
    //do something with the exception
  }
}

Calling the get() method inside the done helps get back any exceptions that were thrown during the doInBackground, so I highly recommend it. SwingWorker uses Callable and Future internally to manage the background thread, which you might want to read up on instead of trying the join/yield approach.

查看更多
再贱就再见
3楼-- · 2020-02-05 13:14

In general, you must hold onto the SwingWorker until it finishes, which you can test by calling isDone() on it. Otherwise just call get() which makes it wait.

查看更多
够拽才男人
4楼-- · 2020-02-05 13:16

Typically anything that needs to be done after a SwingWorker completes its background work is done by overriding the done() method in it. This method is called on the Swing event thread after completion, allowing you to update the GUI or print something out or whatever. If you really do need to block until it completes, you can call get().

NB. Calling get() within the done() method will return with your result immediately, so you don't have to worry about that blocking any UI work.

查看更多
Emotional °昔
5楼-- · 2020-02-05 13:21

Calling get() will cause the SwingWorker to block.

From the Javadocs:

T get() 
      Waits if necessary for the computation to complete, 
      and then retrieves its result.

Your code will then look like:

public static void main(String args[])
{
    Test t = new Test();
    t.doTask();
    t.get();  // Will block
    System.out.println("done");
}
查看更多
登录 后发表回答