Здесь число вопросов. Прежде всего, вы должны понимать, что вся активная работа требует потока. Эти потоки приходят из пула потоков, который обычно устанавливается равным 1000 из коробки. Это означает, что с самого начала вы исчерпываете пул потоков с таким количеством задач, так что, скорее всего, 2000 из них находятся в очереди. Async помогает , но это не волшебство. Некоторые потоки могут в конечном итоге вернуть пул после того, как запрос завершится, но переключение потоков не гарантируется. Несмотря на это, вы по-прежнему истощаете пул потоков быстрее, чем можете его заполнить.
Тогда неясно, что на самом деле происходит здесь, потому что есть несколько слоев, и вы кормите нас ложкой за один раз. Вы опубликовали, что делает GetPerformanceCounters
, но теперь неясно, что делает RemoteKustoProvider.RunWorkSpaceQueryAsync
. В какой-то момент вы используете что-то вроде HttpClient
, чтобы в конечном итоге сделать запрос в Azure. В зависимости от того, как вы это делаете (и, честно говоря, исходя из качества этого кода, я не очень надеюсь, что вы делаете это правильно), вы, вероятно, также исчерпывает пул соединений. Это гораздо более ограниченный ресурс, так что это означает, что ваша пропускная способность резко снижается, что приводит к дальнейшему увеличению объема цепочки.
Далее, даже если вы могли бы просто взорвать все 3000 запросов одновременно, это по сути равносильно DDoS-атаке на сервер получателя. Я совсем не удивлюсь, если вы на самом деле задушены или заблокированы брандмауэрами на другом конце. Это, конечно, - как вы уже догадались, - является узким местом и во всем остальном.
Наконец, даже если все эти функции, как вы и предполагали, запуск 3000 задач - это не то же самое, что «параллельная обработка». Для этого вам нужно использовать класс Parallel
из TPL.
Я не уверен, что ваша конечная цель здесь, но, безусловно, есть более эффективный способ сделать это, отправив 3000 отдельных запросов. Если там действительно нет, то вам нужно их пакетировать - отправлять несколько раз в течение более длительного периода. Весь процесс должен быть перенесен на внешний процесс и должен быть просто запланирован вашим веб-приложением. Затем вы можете использовать что-то наподобие SignalR для отправки обновлений и, в конечном итоге, обратно к пользователю, когда все это завершится.