事件驱动架构的传统代码模式是将事件连接到函数(回调)并响应外部触发器。
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
}
}
}
答案 0 :(得分:2)
事件驱动架构的传统代码模式是将事件连接到函数(回调)并响应外部触发器。
aysnc await的优点之一是代码可以线性处理以提高可读性。
这两个都是对的,但是根本不同。区别在于“推”系统和“拉”系统之间。在“推送”系统中,您的应用程序接收传入的事件并必须对其进行响应。在“拉”系统中,您的应用程序可以访问某些外部系统并提取数据。
基于推送的系统包括事件驱动的体系结构和System.Reactive(响应式扩展/ Rx)。
基于拉的系统包括async
/ await
和即将推出的“异步流”。
使用事件(或Rx)来处理基于推送的事件没有错。我不会仅将代码更改为“使用async
”。但是,从基于拉式的方向编写代码时,可以更好地理解某些代码,在这种情况下,您可以创建桥。
为了在推拉之间架起桥梁,您需要某种缓冲或背压系统。有几种这样的系统可用,例如System.Threading.Channels和TPL Dataflow,以及一些Rx运算符。因此,例如,您可以有一个事件(基于推送),该事件将消息写入缓冲每个消息的Channel中,并有一个单独的async
阅读器(基于Pull),它从Channel中读取这些消息并进行处理