0

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

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

D .Stark
  • 1,092
  • Имеет смысл ВСЁ делать асинхронным. Если у вас все асинхронно, то у вас везде await, а значит (без дополнительных усилий в виде SyncronizationContext) все это будет перемалываться в пуле потоков. – vitidev Sep 20 '22 at 00:05
  • Абстрактный вопрос про абстрактный код в абстрактных условиях выполнения. Ну например вот решение. Не походит? А что подходит, вы не написали. Вопрос предлагаю удалить, либо конкретизировать. – aepot Sep 20 '22 at 04:20
  • "Абстрактный вопрос" - Так и есть. Я не создаю серверное приложение, это теоретический вопрос про использование асинхронных методов. Вопрос в другом: следует ли делать Process асинхронным и будут ли все задачи выполняться в одном потоке? – D .Stark Sep 20 '22 at 08:41
  • это теоретический вопрос - сделайте его практическим, начните писать код. А класс System.Diagnostics.Process вообще непонятно при чем тут. Отдельный процесс не может работать в одном потоке с текущим. Операционная система запускает каждый новый процесс в одтельном потоке, и это не изменить не переписав саму операционную систему. – aepot Sep 20 '22 at 11:07
  • Process - название метода, обрабатывающего соединения - это есть в вопросе. – D .Stark Sep 20 '22 at 11:14
  • "сделайте его практическим, начните писать код" - Зачем же? Какой информации о методе Process вам не хватает, чтобы дать ответ? – D .Stark Sep 20 '22 at 11:15
  • Process это класс в .NET, я советую переименовать метод, потому что это сбивает с толку. Чтобы дать ответ, надо понять вопрос, я не понимаю. Какой-то поток сознания. Всё смешалось, потоки, асинхронность, каша какая-то. А я вам трижды уже писал, чтобы перестали путать асинхронность и многопоточку. Хотите конкретный ответ, задайте конкретный вопрос. – aepot Sep 21 '22 at 05:32
  • "Какой-то поток сознания. Всё смешалось, потоки, асинхронность, каша какая-то." - В вопросе чётко сказано: "Далее каждое соединение должно обрабатывается в отдельном потоке методом Process". – D .Stark Sep 21 '22 at 15:56
  • "А я вам трижды уже писал, чтобы перестали путать асинхронность и многопоточку." - Как вы по 2 моим последним комментариям поняли, что я путаю асинхронности и многопоточность? Я лишь указал, что Process - название метода и спросил какую информацию об этом методе вы хотели бы услышать. А разницу между 2 этими понятиями я понял в ходе нашего обсуждения ранее. – D .Stark Sep 21 '22 at 15:59
  • "я советую переименовать метод, потому что это сбивает с толку" - Речь не о реальном проекте, вопрос чисто теоретический. Название дано для наглядности ситуации. В плане именования в реальном коде, возможно вы правы. – D .Stark Sep 21 '22 at 16:01

1 Answers1

1

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

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

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

}

await someTasksContainer.WaitForAllTasks();

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

Pavel Mayorov
  • 58,537