8

私は共通の問題に違いないものに出くわしました。いくつかの異なるクラスによってサブスクライブされる可能性のあるイベントがある場合、これらのクラスのいずれかによって例外がスローされると、コールバック チェーンが強制終了されます。コールバックが実行される順序がアプリオリにわからないため、これにより、一部のクラスでは予測できない状態変化が発生し、他のクラスでは発生しない可能性があります。

聖書(C# 経由の CLR、私は C# 2.0 を使用しています)には、MulticastDelegate.GetInvocationListこれを回避するための使用に関する短い段落がありますが、それ以上のものはありません。だから私の質問は、これに対処する最善の方法は何ですか? MulticastDelegate.GetInvocationListイベントがあるたびに使用する必要がありますか?? それとも、ある種のロールバック メカニズムでデリゲート チェーンの一部として呼び出される可能性があるすべてのメソッドを囲む必要がありますか? C# で非常に使いやすい単純なイベント/デリゲート モデルと比較して、これらすべてのオプションが非常に複雑なのはなぜですか? そして、破損した状態にならずに簡単な方法を使用するにはどうすればよいですか?

ありがとう!

4

2 に答える 2

12

単にデリゲートを呼び出すと、すべてのターゲット メソッドが順番に呼び出されます。GetInvocationListそれらを個別に実行する場合は、使用する必要があります-例:

  • Cancel毎回チェックする
  • それぞれの戻り値を取得する
  • 個々のターゲットが失敗した後も続行する

それを使用する最良の方法については、どのように動作させたいですか? 私には明らかではありません...たとえば、これは拡張メソッドに非常に適している可能性があります。

static void InvokeIgnoreErrors(this EventHandler handler,
        object sender) {
    if(handler != null) {
        foreach(EventHandler subHandler in handler.GetInvocationList()) {
            subHandler(sender, EventArgs.Empty);
        }
    }
}

myHandler.InvokeIgnoreErrors(this);次に、 (たとえば)呼び出すだけです。

別の例は次のとおりです。

static bool InvokeCheckCancel(this CancelEventHandler handler,
        object sender) {
    if(handler != null) {
        CancelEventArgs args = new CancelEventArgs(false);
        foreach(CancelEventHandler subHandler in handler.GetInvocationList()) {
            subHandler(sender, args);
            if(args.Cancel) return true;
        }
    }
    return false;
}

最初のイベントがキャンセルを要求した後に停止します。

于 2009-01-12T09:19:14.793 に答える