At the moment of time, 300 tasks are started (this launch occurs periodically in a couple of minutes). A method that runs inside a task generates several asynchronous requests to an external source. Given that a lot of tasks, and the answer from an external source can be for several minutes, then because of this, unnecessary streams are created. Unnecessary in the sense that at the same time by the working machine they cannot be processed and it is necessary to spend time switching between them. The question is how can I limit the number of threads (i.e., to run 15 tasks in one thread as the workstation allows you to execute 20 threads in parallel) that will be used to process these tasks. Possible options are limiting the number of threads in ThreadPool or launching via Parallel.For with the MaxDegreeOfParallelism parameter set. But there is a condition that the completed asynchronous operation must continue to work in the stream in which it started / was launched. I will be glad to any help or sources where I can see the idea of ​​implementation.
Upd. Regarding why a thread is created to start an asynchronous operation. There are a lot of sources to which requests occur - and they are different. Therefore, one instance that is launched via Task.Run () is a call to only one external source. Those. 300 tasks are 300 different sources. Also, this data is further processed with its own logic.