2011-06-29 9 views
22

私はSwing Workerクラスを通してアプリケーションでスレッドを使用しています。それはうまく動作しますが、try-catchブロックにエラーメッセージダイアログを表示するのは悪い思いです。潜在的にアプリケーションをブロックできますか?これは現在の外観です:スイングワーカーでの優雅な例外処理

SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { 

    // Executed in background thread 
    public Void doInBackground() { 
     try { 
      DoFancyStuff(); 
     } catch (Exception e) { 

      e.printStackTrace(); 

      String msg = String.format("Unexpected problem: %s", e 
        .toString()); 

      //TODO: executed in background thread and should be executed in EDT? 
      JOptionPane.showMessageDialog(Utils.getActiveFrame(), 
        msg, "Error", JOptionPane.ERROR_MESSAGE, 
        errorIcon); 

     }//END: try-catch 

     return null; 
    } 

    // Executed in event dispatch thread 
    public void done() { 
     System.out.println("Done"); 
    } 
}; 

Swing Workerフレームワークを使用して安全に行うことはできますか? publish()メソッドのオーバーライドはここで良いリードですか? EDIT

はこのようにそれをやった:

} catch (final Exception e) { 

    SwingUtilities.invokeLater(new Runnable() { 

     public void run() { 

      e.printStackTrace(); 

      String msg = String.format(
        "Unexpected problem: %s", e.toString()); 

      JOptionPane.showMessageDialog(Utils 
        .getActiveFrame(), msg, "Error", 
        JOptionPane.ERROR_MESSAGE, errorIcon); 

     } 
    }); 

} 

計算部分が例外をスローするように、2つのtry-catchブロックにつながるdoneメソッドで取得呼び出すので、私はこれがあると思います最後にクリーナー。

答えて

13

1つのオプションは、EDT

SwingUtilities.invokeLater(new Runnable(){ 
    @Override 
    public void run(){ 
     JOptionPane.showMessageDialog(
      Utils.getActiveFrame(), 
      msg, 
      "Error", 
      JOptionPane.ERROR_MESSAGE, 
      errorIcon); 
    } 
}); 

上のアクションを投稿するSwingUtilities.invokeLater(...)を使用することですそして、あなたが述べたように、SwingWorkerは、中間結果を報告することが可能であるが、あなたはときに呼び出される、process(...)をオーバーライドする必要がありますpublish(...)が呼び出されます。

例外が発生した場合にフラグを設定するだけで、そのフラグが設定されている場合、EDTで安全に実行されるので、done()でダイアログを表示してください。

+4

done()メソッドでの処理は、これまで私がこの状況に近づいてきた方法です。 invokeLaterも素晴らしい解決策です。 – jzd

+0

はい、そうではありませんが、OPの質問に答える+1 – mKorbel

+1

1)SwingWorker内で例外がスローされる可能性のあるコードを実行することは決してできません2)PropertyChangeListenerはSwingWorkerからの例外をキャッチします3)このように問題が起きます:-) – mKorbel

1

あなたは正しいですが、イベントディスパッチスレッド以外の場所でGUIを変更しないSwingの基本ルールに違反しています。

私の場合は、GUIがエラーメッセージを表示するためにリッスンするイベントをスローします。または、SwingWorkerの呼び出しをtry catchでラップし、そこでダイアログを表示することができます。

51

次のようにそれを行うための正しい方法は次のとおりです。

SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { 
    // Executed in background thread 
    protected Void doInBackground() throws Exception { 
     DoFancyStuff(); 
     return null; 
    } 

    // Executed in EDT 
    protected void done() { 
     try { 
      System.out.println("Done"); 
      get(); 
     } catch (ExecutionException e) { 
      e.getCause().printStackTrace(); 
      String msg = String.format("Unexpected problem: %s", 
          e.getCause().toString()); 
      JOptionPane.showMessageDialog(Utils.getActiveFrame(), 
       msg, "Error", JOptionPane.ERROR_MESSAGE, errorIcon); 
     } catch (InterruptedException e) { 
      // Process e here 
     } 
    } 
} 

あなたがバックグラウンドスレッドで例外をキャッチするのではなく、彼らがSwingWorkerの自体に通過させ、その後、あなたがそれらを得ることができますしようとするべきではありませんdone()メソッドを呼び出してget()を呼び出すと、通常doInBackground()(状況に応じてVoid)という結果が返されます。バックグラウンドスレッドで例外がスローされた場合はの中にラップされたget()がスローされます。

また、無効にされたSwingWorkerのメソッドはprotectedであり、それらを作成する必要はありません。public

+0

これはtry-catch-finallyブロックのネストされたクラス内でSwingWorkersメソッド/ funcionality(ies)を作成しました:+)+1 – mKorbel

+0

私のテストではこれもうまくいますが、私の場合は多くのコードを追加します。計算部分が例外をスローするので、try-catchの2つのブロックを追加する必要があります。しかし、心に留めておくべきSth。 – fbielejec

+2

この場合、 'SwingWorker'をなぜ使用しているのか不思議に思うかもしれません。関連する' SwingWorker'機能を使用していないので、独自のスレッドをバックグラウンドで使用しないでください。あなたのコードはバックグラウンドスレッドの中断を処理しないことにも注意してください。 – jfpoilpret