非同期イベントハンドラの完了をイベント発行元で待機する

普通にEventHandlerを使ってイベントを実装すると、非同期のイベントハンドラを登録してもInvoke()で完了を待機できない。

Before Invoke
After Invoke
1

EventHandlerはvoid型のdelegateなので待機できない。

全ての非同期のイベントハンドラの完了をイベント発行元で待機するには、自分でTaskを返すdelegateを定義してイベントとして公開し、マルチキャストデリゲートをTask.WhenAll()で待機すればよい。GetInvocationList()の戻り値はDelegate[]型なのでOfType()で元の型にキャストしている。まとめて拡張メソッドにしてしまっても良い。

Before Invoke
1
2
After Invoke

ここでSelectにasyncラムダを渡しているが、Selectはこれを待機しないのでawaitのタイミングで後続のイベントハンドラが走り始めて並列になる。イベントハンドラを逐次実行したい場合の実装例は以下を参照。

cactuaroid.hatenablog.com