首頁 >後端開發 >C++ >如何使 C# 事件異步?

如何使 C# 事件異步?

Mary-Kate Olsen
Mary-Kate Olsen原創
2025-01-08 12:31:41726瀏覽

How to Make C# Events Asynchronous?

C#非同步事件的優雅處理方法

在C#應用程式中,如果一個類別包含事件(例如'GameShuttingDown'事件),而事件處理程序是非同步的,可能會出現遊戲在等待的事件處理程序完成之前就關閉的問題。這是因為事件本身是同步的,而處理程序卻是非同步的。

雖然可以使用非同步機制來取代事件,但這會損失事件的簡潔性。更好的方法是保持事件的表達能力,同時實現非同步處理。 我們可以透過自訂委託類型,而非使用標準的EventHandler來實現。

以下範例顯示如何實現:

<code class="language-csharp">public class A
{
    public event Func<object, EventArgs, Task> Shutdown;

    public async Task OnShutdown()
    {
        var handler = Shutdown;

        if (handler == null)
        {
            return;
        }

        var invocationList = handler.GetInvocationList();
        var handlerTasks = invocationList.Select(h => ((Func<object, EventArgs, Task>)h)(this, EventArgs.Empty)).ToArray();

        await Task.WhenAll(handlerTasks);
    }
}</code>

OnShutdown()方法中,我們先取得事件委託的本地副本。然後,我們呼叫所有處理程序,並將傳回的任務儲存在一個陣列中。最後,我們使用Task.WhenAll()等待所有任務完成。 這比循環迭代更簡潔。

以下是一個簡單的控制台程序,演示了使用方法:

<code class="language-csharp">public class Program
{
    public static void Main(string[] args)
    {
        var a = new A();

        a.Shutdown += Handler1;
        a.Shutdown += Handler2;
        a.Shutdown += Handler3;

        a.OnShutdown().Wait();
    }

    public static async Task Handler1(object sender, EventArgs e)
    {
        Console.WriteLine("启动关闭处理程序 #1");
        await Task.Delay(1000);
        Console.WriteLine("关闭处理程序 #1 完成");
    }

    public static async Task Handler2(object sender, EventArgs e)
    {
        Console.WriteLine("启动关闭处理程序 #2");
        await Task.Delay(5000);
        Console.WriteLine("关闭处理程序 #2 完成");
    }

    public static async Task Handler3(object sender, EventArgs e)
    {
        Console.WriteLine("启动关闭处理程序 #3");
        await Task.Delay(2000);
        Console.WriteLine("关闭处理程序 #3 完成");
    }
}</code>

這種方法保留了事件的簡潔性,同時確保處理程序非同步執行,避免了同步阻塞問題。 使用LINQ的Select方法簡化了程式碼,使其更易於閱讀和維護。

以上是如何使 C# 事件異步?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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