Как подождать метод 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()
, что заставляет его ждать.