Как мне ждать метода doInBackground () SwingWorker? - PullRequest
13 голосов
/ 24 ноября 2010

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

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(), прежде чем распечатывать «готово», но я точно не знаю, как именно. Я знаю, что мне, вероятно, следует использовать join() здесь, но мне нужен поток для его вызова, и я не знаю, как получить поток doInBackground(), откуда мне нужно вызвать join(). Спасибо за любую помощь.


РЕДАКТИРОВАТЬ: Спасибо за ответы. К сожалению, get() и т.п. не совсем решают проблему. В моем реальном коде SwingWorker также имеет переопределенную функцию process(), которая обновляет окно графического интерфейса во время работы фонового потока. get() останавливает печать «готово» до doInBackground, но графический интерфейс не обновляется. Я обновил мой пример кода, чтобы отразить это, хотя теперь, конечно, он не будет компилироваться.

Есть ли способ выполнить "готово" к печати только после завершения doInBackground? Код обновления графического интерфейса и оператор «done» находятся в одном потоке? Нужно ли создавать новую тему?

Ответы [ 4 ]

11 голосов
/ 24 ноября 2010

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

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

9 голосов
/ 24 ноября 2010

Вызов 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");
}
5 голосов
/ 30 ноября 2010

Вы можете переопределить метод 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 () внутри объекта done помогает вернуть любые исключения, которые были сгенерированы во время doInBackground, поэтому я настоятельно рекомендую это сделать. SwingWorker использует Callable и Future для внутреннего управления фоновым потоком, о котором вы, возможно, захотите прочитать, вместо того, чтобы использовать метод объединения / выхода.

0 голосов
/ 24 ноября 2010

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

...