Как подождать метод DoInBackground() SwingWorker?

Скажем, у меня есть следующий код:

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");
    }
}

Мне нужно подождать до тех пор, пока t.doTask() не будет завершено, пока не будет напечатано "done", но я точно не знаю. Я знаю, что я, вероятно, должен использовать join() здесь, но мне нужен поток для его вызова, и я не знаю, как получить поток doInBackground(), откуда мне нужно позвонить join(). Спасибо за любую помощь.


EDIT: Спасибо за ответы. К сожалению, get() и тому подобное не совсем решают проблему. В моем фактическом коде SwingWorker также имеет переопределенную функцию process(), которая обновляет окно GUI во время работы фонового потока. get() останавливает 'done' от печати до doInBackground, но тогда GUI не обновляется. Я обновил свой пример кода, чтобы отразить это, хотя теперь, конечно, он не будет компилироваться.

Есть ли способ сделать "сделан" для печати только один раз doInBackground закончен? Код обновления GUI и оператор "done" в том же потоке? Мне нужно создать новый поток?

Ответы

Ответ 1

Обычно все, что нужно сделать после завершения SwingWorker фоновой работы, выполняется путем переопределения метода done(). Этот метод вызывается в потоке событий Swing после завершения, позволяя вам обновлять GUI или распечатывать что-то или что-то еще. Если вам действительно нужно заблокировать, пока он не завершится, вы можете вызвать get().

NB. Вызов get() в методе done() немедленно вернется с вашим результатом, поэтому вам не придется беспокоиться о том, что блокирует работу любого пользовательского интерфейса.

Ответ 2

Вызов get() приведет к блокировке SwingWorker.

Из Javadocs:

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

Затем ваш код будет выглядеть следующим образом:

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

Ответ 3

Вы можете переопределить метод done(), который вызывается, когда doInBackground() завершен. Метод done() вызывается в EDT. Так что-то вроде:

@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
  }
}

Вызов метода get() внутри сделанного помогает вернуть все исключения, которые были выбраны во время doInBackground, поэтому я настоятельно рекомендую его. SwingWorker использует Callable и Future внутренне для управления фоновым потоком, который вы, возможно, захотите прочитать, вместо того, чтобы пытаться использовать метод join/yield.

Ответ 4

В общем, вы должны держаться на SwingWorker до тех пор, пока он не закончится, который вы можете проверить, вызвав isDone() на нем. В противном случае просто вызовите get(), что заставляет его ждать.