Как обрабатывать внешние события с помощью асинхронного ожидания? - PullRequest
0 голосов
/ 05 апреля 2019

Традиционный шаблон кода для архитектуры, управляемой событиями, заключается в подключении событий к функциям (обратным вызовам) и реагированию на внешние триггеры.

Одним из преимуществ 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 Ответ

2 голосов
/ 05 апреля 2019

Традиционный шаблон кода для архитектуры, управляемой событиями, заключается в подключении событий к функциям (обратным вызовам) и реагировании на внешние триггеры.

Одним из преимуществ aysnc await является код, который обрабатывается линейно для лучшей читаемости.

Оба они верны, но они принципиально разные. Разница между «толкающей» системой и «вытягивающей» системой. В «активной» системе ваше приложение получает входящие события и должно реагировать на них. В «вытягивающей» системе ваше приложение обращается к какой-либо внешней системе и извлекает данные.

Системы на основе Push включают управляемую событиями архитектуру и System.Reactive (Reactive Extensions / Rx).

Системы на основе Pull включают async / await и предстоящие «асинхронные потоки».

Нет ничего плохого в использовании событий (или Rx) для обработки событий на основе push. Я бы не стал менять код просто на «использование async». Тем не менее, некоторый код может быть лучше понят при написании с ориентацией на основе извлечения, и в этом случае вы можете создать мост.

Для того, чтобы соединить толчок и тягу, вам нужна какая-то система буфера или противодавления. Доступно несколько таких систем, например, System.Threading.Channels и TPL Dataflow, а также некоторые Rx-операторы. Таким образом, вы можете, например, иметь событие (на основе push), которое записывает сообщения в канал, который буферизует каждое сообщение, и иметь отдельное async считыватель (на основе pull), который читает эти сообщения из канала и обрабатывает их.

...