2009-07-23 8 views
3

私は複数のステップでタスクにフィードできるアプリを書いています。私は以下のコードに似たコードをいくつか持っており、これが例外を処理する通常の方法かどうかを知りたいと思っています。このコードはおそらく他の誰にも見られませんが、それは可能性がありますので、誰もが期待するように例外を処理していることを知りたいと思います。例外を処理するのはいつですか?

IEnumerable<Task> Tasks; 

foreach(var task in Tasks) 
{ 
try 
{ 
    //boiler plate prep for task (loading libraries, connecting, logging start, etc) 

    foreach(var step in task.Steps) 
    { 
     try 
     { 
     step.Execute(); 
     } 
     catch(Exception ex) 
     { 
     LogStepError(step, ex); 
     throw; 
     } 
    } 

    //Notify parties task has been completed successfully, log task completion 
    } 
    catch(Exception ex) 
    { 
     LogTaskFailure(task); 
    } 
    finally 
    { 
    //close connections, etc 
    } 
} 



interface ITaskStep 
{ 
    void Execute() 
    { 

    }    
} 

私はまた、タスク手順ITaskStepインタフェースを実装していることを追加したいので、実行の実装は(うまくそれがこの例である、誰かがインターフェイスを実装できる)私自身ではありません。私のコードはライブラリをロードし、ITasksとそのITaskStepを実行します。

答えて

7

は先に行くと自分の存在をログに記録する例外をキャッチ。しかし、実際に例外がスローされる原因となった問題を解決していない場合は、呼び出し側が処理するために再スローしてください。それを飲み込まないでください。

上記のコードでは、TaskIsBogusExceptionPrinterOnFireExceptionがあり、同じ方法で処理されます。ログに記録して、次の作業を続けてください。とにかく仕事を済ませているので、偽の仕事でそれをやってもいいですが、PrinterOnFireExceptionを捕まえてそれをやり直さないと、ゴリによってプリンターはまだ火をつけていない方がいいです。

再スローするつもりがない場合は、コードがその時点でどのように処理するかを知っている特定の例外タイプだけをキャッチします。他のすべてのものを(あなたが扱う方法を知らないか、または決して考えていないもの)次の利用可能な例外ハンドラまで伝播します。

0

私はいくつかのタスクが失敗しても完了したいタスクのリストを持っているときに、何回か同じようなことをしました。実際には、失敗する可能性が高いことが分かっている時がありますが、すべての手順が完了するまでループから脱出したくありません。

多くの意味があると思います。

2

step.Execute()は、あなたのためのループ内で起こっている唯一のものである場合には、以下が良いかもしれない:(明確化に応じて編集した)

IEnumerable<Task> Tasks; 

foreach(var task in Tasks) 
{ 
    try 
    { 
    //boiler plate prep for task 
    } 
    catch(Exception ex) 
    { 
    LogTaskFailure(task); 
    continue; 
    } 
    foreach(var step in task.Steps) 
    { 
     try 
     { 
     step.Execute(); 
     } 
     catch(Exception ex) 
     { 
     LogStepError(step, ex); 
     LogTaskFailure(task); 
     break; 
     } 
    } 
} 

class TaskStep 
{ 
    private void Execute() 
    { 
     //do some stuff, don't catch any exceptions 
    }    
} 

あなたは例外を再スローしていないこの方法では。

+0

ボイラープレートの準備は、ループの外側で起こっているいくつかの他のものですが、私はtry/catchでラップしたいものです。 – scottm

+0

このコードでは、ボイラープレートコードが例外をスローすると、それ以上のタスクは実行されず、それは私が望むものではありません。 – scottm

+0

まあ、私はまた、すべての接続を処理するためにfinallyブロックを使用する必要があります。私の最初の例は最も代表的ではなかったと思います。 – scottm

0

私はこれのように書いているかもしれないと思うが、あなたは方法も働く。

foreach(var step in task.Steps) 
     { 
      try 
      { 
      step.Execute(); 
      } 
      catch(Exception ex) 
      { 
      LogStepError(step, ex); 
      LogTaskFailure(task); 
      break; 
      } 
     } 
0

あなたはリターンvaribaleを使用して、タスクの完了を処理し、任意の一般的な例外をキャッチするために全体のコードpience上の例外を使用する場合があります。

例:

try{ 
foreach(var step in task.Steps) 
     { 
      if(!step.Execute()){ 
       break; 
      } 

     } 
}catch(Exception ex) 
{ 
} 
2

あなたはOKであり、あなたが述べたように、最も一般的なアプローチですが、私はそれが正しいものであるとは思わないすべての例外をキャッチしています。

私はあなたが特定の例外を捕まえるべきだと思います。あなたがそうするならば、あなたはそれらを分けることができ、あなたは単に扱うことができないいくつかの例外があることに気付くでしょうが、あなたができることが他にあります。あなたのコードで何が起こっているかを正確に知るので、コードはより良く、より堅牢になります。

これは一例です:



try 
{ 
    //Your stuff 
} 
catch(DivideByZeroException ex) 
{ 
    //Could you manage this? 
} 
catch(NullReferenceException ex) 
{ 
    //Could you manage this one? 
} 
catch(IOException ex) 
{ 
     //What about this one? 
} 
finally 
{ 
     //Any cleanup code 
} 

+0

私は将来このようなことをするつもりですが、最初に考え出された一般的な設定を取得する必要があります。 – scottm