Consider the following code:
async Task Go()
{
var task1 = PrintAnswerToLife();
var task2 = PrintAnswerToLife();
await task1; await task2;
}
async Task PrintAnswerToLife()
{
var task = GetAnswerToLife();
int answer = await task; Console.WriteLine(answer);
}
async Task<int> GetAnswerToLife()
{
var task = Task.Delay(5000);
await task; int answer = 21 * 2; return answer
}
Question 1:
In chapter 14, page 588, of the book "C# 5.0 in a Nutshell" by the Albahari brothers, it is stated that the two asynchronous operations task1 and task2 run in parallel. That does not seem correct to me. As far as I understand, when var task1 = PrintAnswerToLife();
runs, the executions goes into PrintAnswerToLife()
where when it hits await
returns execution to Go()
, and proceeds to the next line var task1 = PrintAnswerToLife();
, where the same thing happens again. In other words there is nothing occurring in parallel in the first two lines of Go()
. In fact, unless there is a thread involved (as in Task.Run()
or Task.Delay()
), no real parallelism ever occurs. Have I understood this correctly? If so, what does Albahari really mean by saying that the two operations run in parallel?
Question 2:
On the same page, Albahari goes on to state the following:
Concurrency created in this manner occurs whether or not the operations are initiated on a UI thread, although there is a difference in how it occurs. In both cases, we get the same concurrency occurring in the bottom-level operations that initiate it (such as Task.Delay, or code farmed to Task.Run). Methods above this in the call stack will be subject to true concurrency only if the operation was initiated without a synchronization context present...
What does Albahari mean by this? I do not understand how a SynchronizationContext
comes into play here, and what difference it makes.