0

I expected that the thread in which the Main method works will be busy executing Task.WaitAll and n-1 threads will remain for the rest of the tasks, where n is the maximum CPU threads in the system. And in the case of using await Task.WhenAll, the thread in which the Main method works will not be busy executing await Task.WhenAll, and n threads will remain for the rest of the tasks. But in reality there is no difference.

Question:

In this example, the advantage of using await Task.WhenAll is precisely that the system does not need to spend resources to create a new "software thread"? Am I thinking right?

Example:

int Tasks = Environment.ProcessorCount * 2;
int Count = 0;
List<Task> MyListForTask = new List<Task>();

void MyMethod()
{
    lock (MyListForTask)
    {
        Count++;
    }

    Console.WriteLine(Count);

    int Sum = int.MaxValue;

    while (Sum > 0)
    {
        Sum--;
    }
}

//Option 1: Task.WaitAll. For a machine with 16 threads: 16 + 16 runs
for (int i = 0; i < Tasks; i++)
{
    MyListForTask.Add(new Task(MyMethod));
    MyListForTask[i].Start();
}
Console.WriteLine("Method Main works");
Task.WaitAll(MyListForTask.ToArray());
Console.WriteLine("\n");

MyListForTask.Clear();
Count = 0;

//Option 2: await Task.WhenAll. For a machine with 16 threads: 16 + 16 runs
for (int i = 0; i < Tasks; i++)
{
    MyListForTask.Add(new Task(MyMethod));
    MyListForTask[i].Start();
}
Console.WriteLine("Method Main works");
await Task.WhenAll(MyListForTask.ToArray());
  • 3
    Open your Windows Task Manager and look at the "Threads" column in the details tab. The total isn't 16. It's probably in the hundreds. – John Wu Nov 15 '22 at 08:12
  • @JohnWu, Thank you. I already guessed that I misunderstood the concept of threads. The answer to my second question is "Yes", now I understand correctly? –  Nov 15 '22 at 08:14

1 Answers1

2

Task.WaitAll blocks the calling thread until all the Tasks complete.

Task.WhenAll creates a Task that completes when all the Tasks complete.

If you wait or await the Task returned by Task.WhenAll the effect is similar.

In no case does the calling thread run all the tasks.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
David Browne - Microsoft
  • 80,331
  • 6
  • 39
  • 67
  • There are only 16 threads CPU in my system, 1 thread should be blocked by Task.WaitAll, there are 15 left, how can 16 tasks be running with 15 free threads? –  Nov 15 '22 at 02:47
  • 4
    The OS time shares the 16 CPU cores among hundreds of threads. – David Browne - Microsoft Nov 15 '22 at 03:07
  • 3
    Task != Thread ... Tasks are primarily used to track I/O operations, which do not require a thread to run. Disk I/O operations are waiting for the hardware to perform the access, for example. Also, there are hundreds, if not thousands, of threads on your system and the OS schedules them for slices of CPU time. Your CPU can only have 16 running code at any time, but they're all getting time if they need to run. The CPU doesn't have threads, it has cores, each of which runs whatever thread is scheduled on it for a few instructions before being moved to another thread. – madreflection Nov 15 '22 at 03:07
  • I understand that I misunderstood the concept of flow. Can someone answer my second question? –  Nov 15 '22 at 08:11
  • @NikVladi you may want to open a new question, asking about the difference between a hardware thread and a software thread. But check first if a similar question already exists. – Theodor Zoulias Nov 15 '22 at 08:13
  • @madreflection *"The CPU doesn't have threads"* -- actually "CPU thread" is a [valid term](https://stackoverflow.com/questions/916048/what-is-a-cpu-thread-and-how-is-it-related-to-logical-threads-in-code). – Theodor Zoulias Nov 15 '22 at 08:17
  • @TheodorZoulias, Thank you. I have changed the question. Just write "Yes" and I'll shut up =). –  Nov 15 '22 at 08:19
  • @TheodorZoulias, **...the effect is similar...** The answer does not mention the advantage of `await Task.WhenAll` over `Task.WaitAll`. Yes, the thread is blocked, and what? If **...the effect is similar...**? Or is there still a difference, for example in the overhead of creating a new "software thread"? –  Nov 15 '22 at 08:27
  • @NikVladi [WaitAll vs WhenAll](https://stackoverflow.com/questions/6123406/waitall-vs-whenall). With the `await Task.WhenAll` you can keep your UI responsive (if you have a UI), or allow the current thread to return to the `ThreadPool` and be available for another request (if you have an ASP.NET application). It's not so much about creating a new thread. It's more about using efficiently the existing threads, by not blocking them. – Theodor Zoulias Nov 15 '22 at 08:32
  • @TheodorZoulias: I'm aware of that. I was trying to draw a sharper distinction between hardware and software because OP's mental model is garbled. And really, it's the **"Task != Thread"** point that was most important there. – madreflection Nov 15 '22 at 15:18
  • @madreflection I think that the [original version](https://stackoverflow.com/revisions/74440044/1) of the question was pointing more to a confusion between hardware thread and software thread, than between software thread and `Task`. Anyway, our friend NikVladi who likes to create many short-lived accounts, will probably find soon some new way to get confused again. – Theodor Zoulias Nov 15 '22 at 15:51
  • They always do. – madreflection Nov 15 '22 at 15:54