Уже спросил на англоязычном форуме, ответы меня не устраивают.
На самом деле я изучаю async/wait и пытаюсь увидеть для себя преимущество await Task.WhenAll по сравнению с Task.WaitAll в операциях, связанных с процессором. Поскольку все пишут, что Task.WaitAll обеспечивает блокирующее ожидание, а await Task.WhenAll обеспечивает неблокирующее ожидание.
Я создал пример, в котором хотел заменить Task.WaitAll на await Task.WhenAll и своими глазами увидеть, что появился еще один свободный поток. Но я вижу, что даже Task.WaitAll не блокирует поток. И мой вопрос связан с этим. В случае с Task.WaitAll я вижу, что в том же потоке, в котором выполняется Task.WaitAll, выполняется другая задача. Но если я включу Thread.Sleep или while (true) вместо Task.WaitAll, то поведение программы станет ожидаемым.
Я думал, что метод Main создаст задачу MyTask (-1 рабочий поток), которая создаст 16 задач условно B1-B16 (-15 рабочих потоков, так как 1 рабочий поток занят задачей MyTask, а всего рабочих потоков 16), задача MyTask будет иметь блокирующее ожидание Task.WaitAll, и я увижу 15 из 16 запущенных задач. Но я вижу все 16 запущенных задач, и одна из них выполняется в том же потоке, что и задача MyTask.
Вопрос.
Почему в этом примереTask.WaitAll не блокирует поток, в котором он выполняется, в отличие от Thread.Sleep или while (true)? Может ли кто-нибудь объяснить пошагово, как работает код двух задач в потоке 4 в случае использования Task.WaitAll? Почему поток, в котором выполняется задача MyTask, также используется условно задачей B16?
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine($"Main Thread: {Thread.CurrentThread.ManagedThreadId}");
int ProcessorCount = Environment.ProcessorCount;
ThreadPool.SetMaxThreads(ProcessorCount, ProcessorCount);
int Counter = 0;
List<Task> MyListForTask = new List<Task>();
void MyMethod()
{
lock (MyListForTask)
{
Counter++;
Console.WriteLine($"Counter: {Counter} Thread: {Thread.CurrentThread.ManagedThreadId}");
}
//Thread.Sleep(int.MaxValue);
while (true) { };
}
Task MyTask = Task.Run(() =>
{
Console.WriteLine($"MyTask Thread: {Thread.CurrentThread.ManagedThreadId}\n");
for (int i = 0; i < ProcessorCount; i++)
{
MyListForTask.Add(Task.Run(MyMethod));
}
//Thread.Sleep(int.MaxValue);
//while (true) { };
Task.WaitAll(MyListForTask.ToArray());
});
MyTask.Wait();
}
}
}



