Использование асинхронности в многопоточном серверном приложении

Cоздаётся многопоточное серверное приложение. Существует цикл в основном потоке, который принимает входящие соединения. Далее каждое соединение должно обрабатывается в отдельном потоке методом Process, который содержит множество вызовов асинхронных методов, читающих или записывающих данные в Stream, представляющий соединение. Имеет ли смысл делать метод Process асинхронным и запускать обработку каждого соединения отдельной задачей? Как минимум это удобно в плане написания кода, ведь вместо использования GetAwaiter().GetResult() можно писать просто await. Так же могут быть задержки связанные с ожиданием получения данных от клиента, которые не будут блокировать поток и он может обрабатывать другие соединения.

Однако, все вызовы асинхронного метода Process, обрабатывающего соединения, будут выполняться в одном потоке (при условии что до начала цикла приёма входящих соединений существовал 1 поток), ведь задача запускается с параметрами по-умолчанию, то есть созданные задачи не будут порождать новые потоки. Верно ли это и как исправить ситуацию?


Ответы (1 шт):

Автор решения: Pavel Mayorov

Однако, все вызовы асинхронного метода Process, обрабатывающего соединения, будут выполняться в одном потоке (при условии что до начала цикла приёма входящих соединений существовал 1 поток), ведь задача запускается с параметрами по-умолчанию, то есть созданные задачи не будут порождать новые потоки. Верно ли это и как исправить ситуацию?

Глупость полная. Вот типичный цикл приёма соединений:

while(…) {
    var connection = await listener.Accept();
    var task = Task.Run(() => Process(connection, token));

    someTasksContainer.Add(task);
}

await someTasksContainer.WaitForAllTasks();

Задачи, создаваемые через Task.Run, могут выполняться в любом потоке пула.

→ Ссылка