Reputation: 10482
Please consider the following code
public static async Task<int> Answer()
{
await Task.Delay(1000);
return 42;
}
static void Main(string[] args)
{
for (int j = 0; j < 20; j++)
{
Console.WriteLine(j +" " + Thread.CurrentThread.IsThreadPoolThread);
if (j == 1)
{
new Task( async ()=>
{
int answer = await Answer();
Console.WriteLine(answer + " " + Thread.CurrentThread.IsThreadPoolThread);
}).Start();
}
Thread.Sleep(200);
}
return;
Can you guess what the CurrentThread.IsThreadPoolThread
when printing answer is?
It appears that Task.Delay(..)
is doing it, for if I remove await, then the answer is False
. However, I can not seem to find that Delay
actually puts stuff on the thread pool in the documentation.
This brings me to the more general question. What in Task does actually start up a thread pool thread besides Run(..)
?
Edit:
Replacing new Task(...)
with Ask()
public static async void Ask()
{
int answer = await Answer();
Console.WriteLine(answer + " " + Thread.CurrentThread.IsThreadPoolThread);
}
yields the same result
Upvotes: 3
Views: 1812
Reputation: 456507
As I describe in my async
/ await
intro post, by default await
will capture the current "context" and use that to execute the continuation (the code after the await
). This "context" is SynchronizationContext.Current
unless it is null
, in which case it is TaskScheduler.Current
.
I also describe using async
on Console apps on my blog. Console apps do not provide a SynchronizationContext
, so the "context" falls back to TaskScheduler.Current
. Since the currently-executing Task
is running on the thread pool, TaskScheduler.Current
is the same as TaskScheduler.Default
, which is the thread pool task scheduler.
This is why your code is resuming on a thread pool thread. It's the correct behavior.
Upvotes: 3