C#の非同期イベント処理の詳しい説明
はじめに
C# イベント メカニズムは、非同期操作を処理するための強力なツールです。ただし、伝統的なイベントは無効であるため、実行が完了するのを待つことはできません。この記事では、非同期イベント処理を実装するためのいくつかの代替方法を検討します。
チャレンジ
次のコード スニペットについて考えてみましょう。ここでは、シャットダウン イベントを非同期タスクで処理する必要があります。
<code class="language-csharp">public event EventHandler<EventArgs> GameShuttingDown; public async Task ShutdownGame() { // ... await this.NotifyGameShuttingDown(); await this.SaveWorlds(); this.NotifyGameShutDown(); // ... } private async Task SaveWorlds() { // ... }</code>
問題は、NotifyGameShuttingDown
イベント ハンドラーがリターンレスであり、ShutdownGame
メソッド内で呼び出すと、イベントが発生する前に非同期保存タスクが完了できないことです。
解決策 1: カスタムの非同期イベント委任
1 つの方法は、タスクを返すカスタム イベント デリゲートを定義して、待機ハンドラーの実行を許可することです。
<code class="language-csharp">public event Func<object, EventArgs, Task> Shutdown;</code>
ShutdownGame
メソッドでは、ハンドラーを次のように呼び出すことができます:
<code class="language-csharp">Func<object, EventArgs, Task> handler = Shutdown; if (handler == null) { return; } Delegate[] invocationList = handler.GetInvocationList(); Task[] handlerTasks = new Task[invocationList.Length]; for (int i = 0; i < invocationList.Length; i++) { handlerTasks[i] = ((Func<object, EventArgs, Task>)invocationList[i])(this, EventArgs.Empty); } await Task.WhenAll(handlerTasks);</code>
解決策 2: 登録ベースの方法
もう 1 つのオプションは、登録ベースのアプローチを使用することです。この場合、コールバックを登録して非同期に実行できます。
<code class="language-csharp">private List<Func<Task>> ShutdownCallbacks = new List<Func<Task>>(); public void RegisterShutdownCallback(Func<Task> callback) { this.ShutdownCallbacks.Add(callback); } public async Task Shutdown() { var callbackTasks = new List<Task>(); foreach (var callback in this.ShutdownCallbacks) { callbackTasks.Add(callback()); } await Task.WhenAll(callbackTasks); }</code>
メモ
おすすめ
推奨されるアプローチは、アプリケーションの特定のニーズによって異なります。既存のコード ベースやイベントベースの設計が多い場合は、カスタム デリゲート メソッドが推奨されます。新しいアプリケーションやイベントに依存しないアプリケーションの場合、登録ベースのアプローチによりパフォーマンスと柔軟性が向上します。
以上がC# で非同期イベントを処理するには?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。