シーケンシャルメソッドを実行する最良の方法は何ですか?
質問
一連のメソッドを x
秒ごとに実行する必要があるプロジェクトでの作業。現在、別の「親メソッド」内にメソッドが含まれており、それらを次々と順番に呼び出すだけです。
class DoTheseThings()
{
DoThis();
NowDoThat();
NowDoThis();
MoreWork();
AndImSpent();
}
次の手順を実行する前に、各メソッドを例外をスローせずに正常に実行する必要があります。そこで、これらの各メソッドを while
と try..catch
でラップし、 catch
でそのメソッドを再度実行します。
while( !hadError )
{
try
{
DoThis();
}
catch(Exception doThisException )
{
hadError = true;
}
}
これは臭くて、あまり乾燥していないようです。同じ方法で新しい機能をラップしないように、これを行うより良い方法はありますか?ある種のデリゲートコレクションは、これを実装する適切な方法ではありませんか?
さらに「適切な」ものがありますか?解決策
解決
Action[] work=new Action[]{new Action(DoThis), new Action(NowDoThat),
new Action(NowDoThis), new Action(MoreWork), new Action(AndImSpent)};
int current =0;
while(current!=work.Length)
{
try
{
work[current]();
current++;
}
catch(Exception ex)
{
// log the error or whatever
// maybe sleep a while to not kill the processors if a successful execution depends on time elapsed
}
}
他のヒント
ある種のデリゲートコレクションは、これを実装する適切な方法ではありませんか?
デリゲートは、この問題を解決するための可能な方法です。
次のようなデリゲートを作成するだけです:
パブリックデリゲートvoid WorkDelegate();
それらを繰り返し実行できるarraylistに入れます。
System.Exceptionをキャッチするべきではないという個人的な宗教的信念があります。より正確には、処理方法がわかっている例外のみをキャッチする必要があります。
それは言われていることですが、あなたが呼び出しているメソッドはそれぞれ異なることをしており、異なる例外がスローされる可能性があると仮定します。つまり、おそらくメソッドごとに異なるハンドラーが必要になるでしょう。
あなたが私の宗教にも従い、2番目のステートメントが真である場合、コードを不必要に繰り返すことはありません。他の要件がない限り、コードを改善するための私の推奨事項は次のとおりです。
1)各メソッド呼び出しの周りではなく、各メソッドにtry-catchを配置します。
2)各メソッド内のキャッチに、知っている例外のみをキャッチさせます。
http://blogs.msdn.com/fxcop /archive/2006/06/14/631923.aspx http://blogs.msdn.com/oldnewthing/archive/ 2005/01/14 / 352949.aspx http://www.joelonsoftware.com/articles/Wrong.html
HTH ...
あなたの例は大丈夫だと思います..ドライな例ですが、仕事はうまくいきます!!実際、このメソッドがdbアクセスを実行する場合..トランザクションを使用して整合性を確保できます...
マルチスレッダープログラムの共有変数を扱う場合..同期を使用する方がクリーンです..コーディングで最も重要なことは、バグの少ない適切なコードを記述することです。正しく..
public void DoTheseThings()
{
SafelyDoEach( new Action[]{
DoThis,
NowDoThat,
NowDoThis,
MoreWork,
AndImSpent
})
}
public void SafelyDoEach( params Action[] actions )
{
try
{
foreach( var a in actions )
a();
}
catch( Exception doThisException )
{
// blindly swallowing every exception like this is a terrible idea
// you should really only be swallowing a specific MyAbortedException type
return;
}
}
エラーが発生した理由は何ですか?
これが接続やオブジェクトなどへのアクセスなどのリソースの問題である場合は、モニター、セマフォ、または単にロックの使用を検討することをお勧めします。
lock (resource)
{
Dosomething(resource);
}
この方法では、以前のメソッドがリソースにアクセスしている場合、リソースを解放して続行するまで待機できます。
理想的には、失敗するたびに何かを実行するためにループを実行する必要はないはずです。それはまったく失敗しているので、問題について知り、修正したいと思うでしょう。常に試行を繰り返すループを持つことは、ここに進む正しい方法ではありません。
Ovidiu Pacurarが提案することを行います。 foreach
ループを使用し、配列インデックスの処理はコンパイラに任せます。
単純なデリゲートアプローチ:
Action<Action> tryForever = (action) => {
bool success;
do {
try {
action();
success = true;
} catch (Exception) {
// should probably log or something here...
}
} while (!success);
};
void DoEverything() {
tryForever(DoThis);
tryForever(NowDoThat);
tryForever(NowDoThis);
tryForever(MoreWork);
tryForever(AndImSpent);
}
スタックアプローチ:
void DoEverything() {
Stack<Action> thingsToDo = new Stack<Action>(
new Action[] {
DoThis, NowDoThat, NowDoThis, MoreWork, AndImSpent
}
);
Action action;
while ((action = thingsToDo.Pop()) != null) {
bool success;
do {
try {
action();
success = true;
} catch (Exception) {
}
} while (!success);
}