2010-11-23 118 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方法。