According to MSDN, async and await do not create new threads:
The
asyncandawaitkeywords don't cause additional threads to be created.
With this in mind, I'm having difficulty understanding control flow of some simple programs. My complete example is below. Note that it requires the Dataflow library, which you can install from NuGet.
using System;
using System.Threading.Tasks.Dataflow;
namespace TaskSandbox
{
class Program
{
static void Main(string[] args)
{
BufferBlock<int> bufferBlock = new BufferBlock<int>();
Consume(bufferBlock);
Produce(bufferBlock);
Console.ReadLine();
}
static bool touched;
static void Produce(ITargetBlock<int> target)
{
for (int i = 0; i < 5; i++)
{
Console.Error.WriteLine("Producing " + i);
target.Post(i);
Console.Error.WriteLine("Performing intensive computation");
touched = false;
for (int j = 0; j < 100000000; j++)
;
Console.Error.WriteLine("Finished intensive computation. Touched: " + touched);
}
target.Complete();
}
static async void Consume(ISourceBlock<int> source)
{
while (await source.OutputAvailableAsync())
{
touched = true;
int received = source.Receive();
Console.Error.WriteLine("Received " + received);
}
}
}
}
Output:
Producing 0
Performing intensive computation
Received 0
Finished intensive computation. Touched: True
Producing 1
Performing intensive computation
Received 1
Finished intensive computation. Touched: True
Producing 2
Performing intensive computation
Received 2
Finished intensive computation. Touched: False
Producing 3
Performing intensive computation
Received 3
Finished intensive computation. Touched: False
Producing 4
Performing intensive computation
Received 4
Finished intensive computation. Touched: True
This seems to indicate that Consume is given control while the for loop is running, as the OutputAvailableAsync task completes:
for (int j = 0; j < 100000000; j++)
;
This would be unsurprising in a threaded model. But if no additional threads are involved, how can Produce yield control in the middle of the for loop?