The continuation of the task was not scheduled in the thread pool thread

I read about SynchronizationContext and its use with async / await methods ( link ). In my opinion, in the Console application, where the SynchronizationContext is null, the continuation of the expected method (Task) will be scheduled with the default scheduler, which will be ThreadPool.

But if I run this console application, you will see on the output that the continuation is performed in the workflow that I created:

class Program { static void Main(string[] args) { Console.WriteLine("MainThreadId=" + Thread.CurrentThread.ManagedThreadId); Method1().ContinueWith(t => { Console.WriteLine("After Method1. ThreadId=" + Thread.CurrentThread.ManagedThreadId); }); Console.ReadKey(); } public static async Task Method1() { Console.WriteLine("Method1 => Entered. ThreadId=" + Thread.CurrentThread.ManagedThreadId); TaskCompletionSource<bool> completionSource = new TaskCompletionSource<bool>(); Thread thread = new Thread(() => { Console.WriteLine("Method1 => Started new thread. ThreadId=" + Thread.CurrentThread.ManagedThreadId); Thread.Sleep(2000); completionSource.SetResult(true); }); thread.Start(); await completionSource.Task; Console.WriteLine("Method1 => After WorkerThread. ThreadId=" + Thread.CurrentThread.ManagedThreadId); } } 

And here is the conclusion:

 MainThreadId=10 Method1 => Entered. ThreadId=10 Method1 => Started new thread. ThreadId=11 Method1 => After WorkerThread. ThreadId=11 After Method1. ThreadId=12 

As you can see, “After WorkerThread” was output in the same thread as my work thread, but not in threadpool.

I found a similar question , but the guy used Mono, and they said it was a mistake. On my side, I built this code in Visual Studio and ran it under Windows 7 and .Net 4.5.2 installed on my machine.

Can anyone explain this behavior?

+5
source share
1 answer

This is because of the implementation detail that I documented on my blog : the continuation created by await is scheduled using the ExecuteSynchronously flag. In this case, when it is time to start the continuation (i.e., in the call to TaskCompletionSource<T>.SetResult workflow), the default scheduler first tries to determine if it can work in the current thread.

Since the workflow does not have a TaskScheduler that will reject the execution of the task synchronously , the ExecuteSynchronously flag will cause the thread pool task scheduler to simply execute the task synchronously (i.e. in the calling thread).

+5
source

Source: https://habr.com/ru/post/1206929/


All Articles