C# での非同期イベントの処理: 非同期操作を安全に待機します
問題の概要:
C# では、イベントは通常、アプリケーション内の特定のイベントをサブスクライバーに通知するために使用される戻り値のないデリゲートです。ただし、非同期イベント ハンドラーを使用しようとすると、問題が発生する可能性があります。イベントは発生しますが、非同期ハンドラーの実行が完了する前にアプリケーションが閉じられてしまいます。
非同期ハンドラーを使用してイベントをサブスクライブします:
イベントを非同期に処理するために、タスクを返すようにイベント シグネチャ自体を変更することはお勧めできません。代わりに、待機可能なコールバック関数を受け入れる登録メソッドを使用できます。これにより、柔軟性が向上し、サードパーティ コンポーネントとの統合が容易になります。
登録メソッドを使用した実装:
<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>
この例では、ShutdownCallbacks
リストには待機可能なコールバック関数が格納されます。 Shutdown()
メソッドは、これらのコールバック関数を反復処理し、同時に待機します。これにより、シャットダウン プロセスが続行される前に、すべての非同期ハンドラーが確実に完了します。
呼び出しリストを使用してイベントを呼び出します:
既存のイベント パラダイムを保持したい場合は、GetInvocationList()
メソッドを使用してハンドラーを順番に呼び出し、返されるタスクを待つこともできます。
<code class="language-csharp">class A { public event Func<object, EventArgs, Task> Shutdown; public async Task OnShutdown() { 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>
ここで、OnShutdown()
はイベント デリゲートを取得し、ハンドラーを呼び出し、その完了を待ちます。
結論:
非同期イベント ハンドラーは魅力的に見えるかもしれませんが、デッドロックやその他の問題が発生する可能性があるため、このアプローチは一般的に推奨されません。前述したように、登録されたメソッドまたは呼び出しリストを使用すると、C# で非同期的にイベントを待機するための、より堅牢で管理が容易なソリューションが提供されます。
以上がC# で非同期イベントを安全に待つ方法?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。