Насколько я понимаю, вызов асинхронного метода внутри цикла с использованием ключевого слова await - совершенно бессмысленно, поскольку цикл продолжит выполняться только после выполнения этого метода.
По этой причине, два нижеследующих варианта с синхронным и асинхронным методом совершенно идентичны:
1.
while (true)
{
var context = listener.GetContext();
Task.run(() => HandleContext(context));
}
2.
while (true)
{
var context = await listener.GetContextAsins();
Task.run(() => HandleContext(context));
}
Таким образом, это делается как-то иначе. Возможно следует просто обернуть асинхронный вызов в другой метод, который уже и вызывать в цикле:
private async void GetContextAsync()
{
var context = await listener.GetContextAsins();
Task.run(() => HandleContext(context));
}
И в цикле:
while(true)
GetContextAsync();
Или, может быть, правильнее это делать так:
while(true)
listener.GetContextAsync().ContinueWith(...);
Пожалуйста, Поправьте меня, если я не прав, и покажите как делать правильно.
Давайте посмотрим, что вам реально нужно. Вам нужно получить новое обращение (контекст), запустить его асинхронно на длительную обработку, и не дожидаясь окончания обработки ожидать прихода нового контекста, правильно?
ожидание -----> пришёл контекст -> ожидание -----------> пришёл новый контекст -> ожидание --
\ \
\ \
обрабатываем контекст -------------------------> закончили
\
обрабатываем новый контекст ----->
Этой схеме соответствует как первый, так и второй цикл. По поводу разницы между первым и вторым вариантом, как уже многие говорили, она лишь в том, что второй вариант не занимает потока на время ожидания. В остальном они выполняются одинаково. Второй вариант предпочтительнее, т. к. занимать поток безделием — нехорошо.
А вот третий вариант с async void, судя по всему, неправильный: async void означает, что содержимое метода запустится, и никто не будет дожидаться его результата. То есть итерации цикла будут бежать одна за другой, не дожидаясь даже окончания получения контекста. В результате у вас будет параллельно висеть очень много незавершённых await listener.GetContextAsync();. Вариант с listener.GetContextAsync().ContinueWith(...); точно так же порождает огромное число параллельных задач ожидания получения контекста.
Эти варианты соответствуют такой диаграмме:
ожидание -----> пришёл контекст
\
\
обрабатываем контекст
ожидание -----> ?
ожидание -----> ?
ожидание -----> ?
ожидание -----> ?
ожидание -----> ?
.
.
.
Вы видите, что одновременно происходит много ожиданий, это явно не то, что вам нужно.
Как развивать веб-проекты в 2026 году: технологии, контент E-E-A-T и факторы доверия
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники