Asynchronous and synchronous contexts
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:
Chapter 14 on page 588 of the Albahari brothers ' C # 5.0 at a Glance indicates that two asynchronous operations task1 and task2 are performed in parallel. It doesn't seem right to me. As I understand it, when var task1 = PrintAnswerToLife();
triggered, execution jumps to PrintAnswerToLife()
when when clicked, it await
returns execution to Go()
and moves to the next line var task1 = PrintAnswerToLife();
where the same thing happens again. In other words, Go()
nothing happens in parallel on the first two lines . In fact, unless a thread is involved (as in Task.Run()
or Task.Delay()
), no real parallelism occurs. Did I understand this correctly? If so, what does Albahari mean by saying that two operations are performed in parallel?
Question 2:
On the same page, Albahari goes on to state the following:
Concurrency created this way occurs regardless of whether the operations are initiated on the UI thread, although there is a difference in how it happens. In both cases, we get the same concurrency occurring in the lower-level operations that initiate it (for example, Task.Delay or the code handled for Task.Run). Methods above this on the call stack will be true concurrency only if the operation was initiated without the presence of a sync context ...
What does Albahari mean? I don't understand how it plays here SynchronizationContext
, and what the difference is.
source to share
Question 1:
Parallel usually means processing multiple threads at the same time. The more precise term for use here is parallel . In your example, both tasks are done at the same time. This means that the asynchronous operation (i.e. await Task.Delay(5000)
) in both tasks is performed at the same time. This is why both tasks will complete in about 5 seconds from the beginning Go
. If the tasks were to be executed sequentially, it would take 10 seconds. Then synchronous continuations will be scheduled on a thread pool thread (unless there is a dedicated one SynchronizationContext
) and there is a chance for parallelism.
Did I get it right?
Yes.
If so, what does Albahari mean by saying that two operations are performed in parallel?
So that they run concurrently and asynchronously with potentially parallel continuations.
Question 2:
Again the explanation is a little oversimplified. This is specific to SynchronizationContext
s, single threaded SynchronizationContext
, used in GUI environments . Since this SynchronizationContext
graph runs all in one particular thread, it doesn't allow for "true concurrency". However, there are others that are multithreaded SynchronizationContext
and you can create your own. Therefore using SynchronizationContext
does not necessarily make concurrency difficult (and you can also turn off capture completely by SynchronizationContext
using ConfigureAwait(false)
for task)
What does Albahari mean?
GUI environments SynchronizationContext
use a single thread that cannot execute anything in parallel.
source to share
In fact, if no thread is involved (as in Task.Run () or Task.Delay ()), no real parallelism occurs. I got it Right?
A thread should only be involved if we are talking about parallelism. Your example about concurrency
Let's break it down:
-
You execute
PrintAnswerToLife
, which in turn launchesGetAnswerToLife
, and right there it reaches its firstawait
onTask.Delay(5000)
. After pressing, it returns toPrintAnswerToLife
, and then returnsawait
Task<int>
, which will cause execution to return toGo
. Meanwhile, start making the second callPrintAnswerToLife
-
The same cycle is performed for
task2
. -
Then
await
each one in sequenceTask
. You could easily expect help from them at the same timeTask.WhenAll
.
What does Albahari mean? I don't understand how SynchronizationContext comes into play here, and what's the difference to make?
A SynchronizationContext
is responsible for your flow of execution. In .NET we have various SynchronizationContext
' s such as DispatcherSynchronizationContext
and WinFormSynchronizationContext
which are responsible for the work of marshaling back to the UI thread (WPF and WinForms respectively). I think it is trying to point out that each of these SynchronizationContext
will eventually march back to some sort of UI message loop that will force it to execute synchronously one by one. If not SynchronizationContext
, the default is used ThreadPoolSynchronizationContext
, which will refer to the continuation of these tasks in the harsh threadpool. This is not entirely true, as you can avoid marshaling the context back to the UI thread with ConfigureAwait(false)
.
source to share