如何在 ASP NET Core 中定义、引发和处理异步事件

How to define, raise and handle async events in ASP NET Core

提问人:Szyszka947 提问时间:1/14/2023 更新时间:1/27/2023 访问量:672

问:

我想用于我的异步事件。但整个话题对我来说似乎很难。delegate

我不知道如何注册事件以及如何注册对所有加薪具有相同逻辑的处理程序。我的意思是,我希望异步事件处理程序始终具有相同的逻辑,该逻辑始终在调用适当的事件时调用。

据我所知,我必须像这样为处理程序使用静态类。但是我不能使用静态类,因为我的处理程序需要使用一些依赖项。

我对此的理解是这样的:enter image description here

我真的不明白如何使用异步事件,以及通常如何正确定义、使用和处理事件。请解释一下,给我一个简单的例子。先谢谢你。

C# ASP.Net-Core 异步 事件 委托

评论

0赞 Qing Guo 1/16/2023
看看这个
0赞 Szyszka947 1/17/2023
@QingGuo 但是异步任务,而不是无效呢?
0赞 ajz 1/21/2023
我不确定委托是否是正确的方法——它们似乎越来越少使用。一些替代方案是反应式扩展 (levelup.gitconnected.com/introduction-to-rx-net-87e4a6c6e71b) 或像 MediatR (github.com/jbogard/MediatR) 这样的库。
0赞 Szyszka947 1/21/2023
但似乎代表是唯一的办法,而不是.我错了吗?async Taskasync void
0赞 GrantByrne 1/25/2023
我认为最好使用 Mediatr 为您服务。它具有异步事件处理功能,还允许您注入所需的依赖项:medium.com/@mohsen_rajabi/...

答:

1赞 Hervé 1/24/2023 #1

异步

使用方法时,通常会将 a 返回给调用方等待。asyncTask

async Task MyAsyncMethod()
{
    // async will implicitly create a new task and return it.
    return;
}

var task = MyAsyncMethod();

// execute the task
await task;

// the task is done

如果不这样做,关键字将执行该方法,因为它无法创建任务。async

async void MyAsyncMethod()
{
    return;
}

// the method execution is started, because it's async
MyAsyncMethod();

事件

通常,事件源 () 只关心引发事件,它不知道有多少监听器,因此它不能排除它们返回值。MyAppEvents

要定义一个事件,你需要做两件事

  • 事件处理程序签名
  • 事件定义(基本上是其名称)
// event handlers signature
public delegate SomeReturnValueType MyEventDelegate(FirstArgType arg1);

// event definition
public event MyEventDelegate MyEventName;

你可以认为你可以用它来从处理程序返回值,但如果你这样做SomeReturnValueType

var result = MyEventName.Invoke();

result将设置为最后一个处理程序的返回值。

混合两者

如果将处理程序定义为返回 a 并在引发事件时尝试返回它们,则只会等待最后一个处理程序的任务。Taskawait

// task only represents the last handler
var task = MyAsyncEvent.Invoke();

await task;

这样做可能会导致混淆,因此我建议将处理程序委托定义为返回 ,因此没有人尝试返回。Taskawait

public delegate void MyAsyncMethod();

引发事件时,执行将继续,因为事件源不知道(也不应该)知道处理程序。

解决方法

利用依赖注入,可以将服务定义为事件处理程序。

public interface IEventHandler<in TEvent>
{
     Task ExecuteAsync(TEvent @event);
}

// custom handler
public class CustomEventHandler : IEventHandler<CustomEvent>
{
     public Task ExecuteAsync(CustomEvent @event)
     {
          // do logic
     }
}

// the event source
public class MyAppEvents
{
     private readonly IEnumerable<IEventHandler<CustomEvent>> _handlers;
    
     public MyAppEvents(IEnumerable<IEventHandler<CustomEvent>> handlers)
     {
          _handlers = handlers;
     }

     private async Task RaiseCustomEventAsync()
     {
        var @event = new CustomEvent();
        
        var tasks = _handlers.Select(h => t.Execute(@event));

        // execute all task and await them
        await Task.WhenAll(tasks);
     }
}

评论

0赞 Szyszka947 1/27/2023
如果它是异步无效的,则存在异常问题。我不能确定该事件是否得到妥善处理。我认为事件更好用。
1赞 Hervé 1/27/2023
@Szyszka947您可以改用服务和 DI。