如何使用异步等待处理外部事件?



事件驱动架构的传统代码模式是将事件连接到函数(回调)并对外部触发器做出反应。

aysnc await 的优点之一是代码可以线性处理以获得更好的可读性。

下面的代码通过将任务放在消息队列上,然后在主循环拉取和进程中对外部触发的事件做出反应(我想对于高度可扩展,这应该是单独的进程)。

我不太明白如何重构使用消息队列来异步等待外部事件(如果这是可取的)。

public class QueueProcessor
{
public SomeMessageQueue MQ;
public delegate void ExternalNotificationHandler(object sender, EventArgs e);
public event ExternalNotificationHandler ExternalNotify;
public QueueProcessor()
{
// configure MQ
ExternalNotify += ProcessExternalNotification;
}
public void ProcessExternalNotification(object sender, EventArgs e)
{
// create new task and add to message queue
}
public void ProcessTasks()
{
while(true)
{
// pull tasks off message queue and process
}
}
}

事件驱动架构的传统代码模式是将事件连接到函数(回调)并对外部触发器做出反应。

aysnc await 的优点之一是代码可以线性处理以获得更好的可读性。

这两者都是正确的,但这些是根本不同的。区别在于"推"系统和"拉"系统。在"推送"系统中,应用程序接收传入的事件,并且必须响应它们。在"拉取"系统中,您的应用程序会访问某个外部系统并拉入数据。

基于推送的系统包括事件驱动架构和 System.Reactive(Reactive Extensions/Rx)。

基于拉动的系统包括async/await和即将推出的"异步流"。

使用事件(或 Rx)来处理基于推送的事件并没有错。我不会仅仅为了"使用async"而更改代码。但是,从基于拉取的方向编写某些代码可以更好地理解,在这种情况下,您可以创建桥接。

为了在推拉之间架起桥梁,您需要某种缓冲或背压系统。有几种这样的系统可用,例如System.Threading.Channels和TPL Dataflow,以及一些Rx运算符。因此,例如,您可以有一个事件(基于推送)将消息写入缓冲每条消息的通道,并有一个单独的async读取器(基于拉取)从通道读取这些消息并处理它们。

最新更新