首頁 >後端開發 >C++ >如何在 C# 中安全地等待非同步事件?

如何在 C# 中安全地等待非同步事件?

Patricia Arquette
Patricia Arquette原創
2025-01-08 12:51:41497瀏覽

How to Safely Await Asynchronous Events in C#?

處理C#中的非同步事件:安全地等待非同步操作

問題概述:

在C#中,事件通常是無回傳值的委託,用於通知應用程式中特定事件的訂閱者。然而,當嘗試使用非同步事件處理程序時,可能會出現一個問題:事件被觸發,而非同步處理程序完成執行之前,應用程式就關閉了。

使用非同步處理程序訂閱事件:

為了非同步處理事件,不建議修改事件簽章本身以傳回Task。相反,您可以使用註冊方法,該方法接受一個可等待的回呼函數。這樣可以提供更大的靈活性和更輕鬆地與第三方組件整合。

使用註冊方法的實作:

<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() 方法順序呼叫處理程序並等待傳回的 Tasks。

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

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