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

时间:2019-04-05 00:09:13

标签: c# asynchronous events async-await message-queue

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

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
        }
    }
}

1 个答案:

答案 0 :(得分:2)

  

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

     

aysnc await的优点之一是代码可以线性处理以提高可读性。

这两个都是对的,但是根本不同。区别在于“推”系统和“拉”系统之间。在“推送”系统中,您的应用程序接收传入的事件并必须对其进行响应。在“拉”系统中,您的应用程序可以访问某些外部系统并提取数据。

基于推送的系统包括事件驱动的体系结构和System.Reactive(响应式扩展/ Rx)。

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

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

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