2010-11-23 54 views
13

说我有下面的代码:如何等待SwingWorker的doInBackground()方法?

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(),但我需要一个线程来打电话给它,并且我不知道如何从我需要拨打join()的地方获得doInBackground()的线程。谢谢你的帮助。


编辑:谢谢你的回应。不幸的是,get()之类并不完全解决这个问题。在我的实际代码中,SwingWorker也有一个覆盖的功能,在后台线程运行时更新GUI窗口。 get()确实停止“完成”,直到doInBackground之后,但是然后GUI不更新。我更新了我的示例代码以反映这一点,虽然现在当然不会编译。

有没有办法让'完成'只打印一次doInBackground完成? GUI更新代码和“完成”语句在同一个线程上?我是否需要制作新的线程?

回答

11

通常,在SwingWorker完成其后台工作后需要完成的任何操作都是通过覆盖其中的done()方法完成的。此方法在完成后在Swing事件线程上调用,允许您更新GUI或打印某些内容。如果你真的需要阻止,直到它完成,你可以拨打get()

注意:在done()方法中调用get()将立即返回结果,因此您不必担心阻止任何UI工作。

+0

好吧,我用`done()`得到了它的工作。谢谢你的帮助。 – Max 2010-11-23 23:27:09

+1

未来googlers的注意事项:当SwingWorker被取消时,这并没有什么帮助。 `done()`可以在`doInBackground()`完成之前运行。 :-(http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6826514 http:// stackoverflow。com/questions/6204141/swingworker-when-exactly-called-done-method – kmort 2015-01-27 21:50:38

9

调用get()将导致SwingWorker阻塞。

从的Javadoc:

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

在一般情况下,你必须守住SwingWorker直到它完成,你可以测试通过调用isDone()它。否则,请致电get(),让它等待。

5

您可以覆盖done()方法,该方法在doInBackground()完成时调用。 EDT上调用done()方法。因此,像:

@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方法。