首頁 >後端開發 >C++ >如何在 C# 中處理非同步事件?

如何在 C# 中處理非同步事件?

Mary-Kate Olsen
Mary-Kate Olsen原創
2025-01-08 12:37:42766瀏覽

How to Handle Asynchronous Events in C#?

C#非同步事件處理詳解

引言

C#事件機制是處理非同步操作的強大工具。然而,傳統的事件是無回傳值的(void),這使得無法等待它們的執行完成。本文將探討幾種實現非同步事件處理的替代方法。

挑戰

考慮以下程式碼片段,其中需要用非同步任務處理一個關閉事件:

<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方法中呼叫它會阻止非同步保存任務在事件觸發之前完成。

解決方案一:自訂非同步事件委託

一種方法是定義一個傳回Task的自訂事件委託,允許等待處理程序的執行:

<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>

解決方案二:基於註冊的方法

另一種選擇是使用基於註冊的方法,其中可以非同步註冊和執行回調:

<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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn