Преобразование синхронной функции в функцию asyn c в C# - PullRequest
0 голосов
/ 05 августа 2020

Я хочу преобразовать (относительно) медленный обработчик событий в async, чтобы избежать блокировки других подписчиков событий. В приведенном ниже примере я не хочу, чтобы другим подписчикам события Message приходилось ждать.

Единственное, что я могу придумать, похоже на «обман»:

client.Message += async (object sender, MessageEventArgs e) => {
    await Task.Run(() => { });
    logger.Info("Some info {0}", e.Message);
}

Конечно, я мог бы обернуть весь вызов logger.Info в Task, но я не понимаю, почему это лучше. Я просто меньше похож на читерство.

Моя единственная другая мысль - оставить обработчик синхронным, а на событие Message следует подписываться только тогда, когда задержка не критична. Таким образом, у меня могло бы быть второе событие, которое используется только подписчиками с низкой задержкой async.

Я ищу здесь отзывы о правильном дизайне кода.

1 Ответ

1 голос
/ 06 августа 2020

Вы можете использовать Task.Yield, если хотите присоединить асинхронный обработчик, который будет вызываться после того, как были вызваны все синхронные обработчики одного и того же события, и вы также хотите, чтобы асинхронный вызов происходил на текущий контекст синхронизации. Для приложения GUI это означает, что вы хотите, чтобы обработчик запускался в потоке пользовательского интерфейса.

client.Message += async (sender, e) =>
{
    await Task.Yield();
    logger.Info("Some info {0}", e.Message);
}

Не используйте await Task.Run(() => { }), потому что это просто многословный, идиоматический c, менее эффективный и (возможно) менее надежная альтернатива await Task.Yield().

Если вы хотите присоединить асинхронный обработчик, который будет работать в потоке ThreadPool (вместо текущего контекста синхронизации), используйте Task.Run:

client.Message += async (sender, e) =>
{
    await Task.Run(() => logger.Info("Some info {0}", e.Message));
}

Это следует делать только в том случае, если вы уверены, что объект logger является потокобезопасным, поддерживает параллельные операции и не требует привязки к потокам (как многие COM компоненты делать).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...