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

2 answers

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?


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.



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 launches GetAnswerToLife

    , and right there it reaches its first await

    on Task.Delay(5000)

    . After pressing, it returns to PrintAnswerToLife

    , and then returns await


    , which will cause execution to return to Go

    . Meanwhile, start making the second callPrintAnswerToLife

  • The same cycle is performed for task2


  • Then await

    each one in sequence Task

    . 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)




All Articles