首页 >后端开发 >C++ >如何在 C# 中安全地等待异步事件?

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

Patricia Arquette
Patricia Arquette原创
2025-01-08 12:51:41502浏览

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