1

I am new to asynchronous programming in C#. Consider the following snippet.

    private static async Task TestAsync(int n)
    {
        Task t = Task.Run(() => Job(ConsoleColor.DarkRed, n));
        Job(ConsoleColor.DarkGreen);
        await t;
        Job(ConsoleColor.DarkBlue);
    }

t is a task that repetitively prints its thread id with red background. t runs on a different thread.

In parallel, Job(ConsoleColor.DarkGreen) repetitively prints its thread id with green background. As it runs on the main thread, it always prints 1.

Finally, Job(ConsoleColor.DarkBlue) repetitively prints with blue background only after all red and green ids get printed. In my understanding the blue one must only print 1 because it runs on the main thread. However, when I increase the n from 10 to 90, I got a contradictory result as follows.

enter image description here

When n=90, the blue one prints a number that is not the same as the main thread id.

Question

Why does the code after await sometimes run on another thread?

Minimal Working Example

using System;
using System.Threading;
using System.Threading.Tasks;
using static System.Console;

class Test
{
    static readonly object obj = new object();

    static void Print(string s, ConsoleColor bc = ConsoleColor.Black)
    {
        lock (obj)
        {
            BackgroundColor = bc;
            ForegroundColor = ConsoleColor.White;
            Write(s);
            ResetColor();
        }
    }

    static void Job(ConsoleColor bc, int n = 50)
    {
        for (long x = 0; x < n; x++)
        {
            Print($"{Thread.CurrentThread.ManagedThreadId} ", bc);
        }
    }

    private static async Task TestAsync(int n)
    {
        Task t = Task.Run(() => Job(ConsoleColor.DarkRed, n));
        Job(ConsoleColor.DarkGreen);
        await t;
        Job(ConsoleColor.DarkBlue);
    }

    static void Main()
    {
        int n = 10;
        Print($"When n = {n}.\n");
        TestAsync(n).GetAwaiter().GetResult();

        n = 90;
        Print($"\n\n\nWhen n = {n}.\n");
        TestAsync(n).GetAwaiter().GetResult();
    }
}
Rufus L
  • 36,127
  • 5
  • 30
  • 43
Second Person Shooter
  • 14,188
  • 21
  • 90
  • 165

1 Answers1

2

Because it can.

You awaited so if the Task wasn't already completed the thread you were running on went back to the pool, potentially to do something useful. Then the Task you were awaiting finished, so a thread was needed to continue. There's no reason why it should be the same thread as before.

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251