2015-09-07 53 views
0

拋出處理由SwingWorker類的doInBackground方法拋出的異常的正確方法例外正確的方法是從done方法中調用get方法,如所解釋herehere來處理由SwingWorker.doInBackground

以下的get方法狀態的文檔:

如有必要,等待計算完成,然後檢索 其結果。

注:在事件指派線程調用​​get所有 事件,包括重新繪製,被處理,直到這 SwingWorker完成。

因此,如果get方法使done方法中的等待,實際上它會阻止在事件指派線程,由於done方法在EDT執行。

但是,執行所提出的方案的一個簡單的測試之後,你可能會注意到該EDT沒有被阻塞:出現這種現象的原因在於get方法在done方法中調用,所以get在操作的結果後調用被計算出來,因此呼籲它不會阻止美國東部時間。這種動機是否正確?

回答

3

因此,如果get方法導致在done方法內等待,事實上它會阻塞Event Dispatch Thread,因爲done方法在EDT上執行。

實際上,如果做被調用時,doInBackground已經返回,因此調用getdone不會阻止事件調度線程。

也是一樣,如果你使用的是PropertyChangeListener支持和監控狀態DONE

更新

這樣的變化,在看看SwingWorker calls 'done' before the 'doInBackground' is finished後,這將意味着調用一個get取消的工作人員會不定期地阻止EDT,基本的工作實際上是通過檢查SwingWorker#isCancelled狀態來忽略返回結果。讓我們面對它,如果工人被取消,返回結果是未知/未定義的,所以最好不要嘗試和get它。

作爲一個例子(基於從錯誤的代碼)

import java.util.concurrent.ExecutionException; 
import javax.swing.SwingWorker; 

public class Main { 

    public static void main(String[] args) throws InterruptedException { 
     SwingWorker<String, String> worker = new SwingWorker<String, String>() { 
      @Override 
      protected String doInBackground() throws Exception { 
       try { 
        while (!Thread.currentThread().isInterrupted()) { 
         System.out.println("Working..."); 
         Thread.sleep(1000); 

        } 
       } catch (InterruptedException ex) { 
        System.out.println("Got interrupted!"); 
       } 

       try { 
        System.out.println("Cleaning up"); 
        Thread.sleep(10000); 
        System.out.println("Done cleaning"); 
       } catch (InterruptedException ex) { 
        System.out.println("Got interrupted second time!"); 
       } 

       return null; 
      } 

      @Override 
      protected void done() { 
       System.out.println("Done"); 
       if (!isCancelled()) { 
        long start = System.currentTimeMillis(); 
        try { 
         get(); 
        } catch (InterruptedException | ExecutionException ex) { 
         ex.printStackTrace(); 
        } 
        long end = System.currentTimeMillis(); 
        System.out.println("Took " + ((end - start)/1000d)); 
       } else { 
        System.out.println("Was cancelled"); 
       } 
      } 
     }; 

     worker.execute(); 

     Thread.sleep(10000); 

     worker.cancel(true); 
     Thread.sleep(20000); 
    } 
} 
+1

檢查一個相關的問題[這裏](http://stackoverflow.com/q/7053865/230513)。 – trashgod

+0

如果使用'cancel',這可能不成立。 (bug)https://bugs.openjdk.java.net/browse/JDK-8081474 – Radiodef

+0

@radiodef理論上,如果取消,得到「應該」拋出一個InterruptedException。我有興趣瞭解ifnthis只是java 8中的一個bug,或者不是 – MadProgrammer

0
@Override 
protected void done() 
{ 
    try 
    { 
     if(!super.isCancelled()) 
     { 
      super.get(); 
     } 
    } 
    catch(Exception ex) 
    { 
     ex.printStackTrace(); 
    } 
}