4

I have a simple question with async programming exposed by the following example:

foreach (var item in result)
{
 property1 = await GetObjectivesQueryable(ObjectiveType.Company, from, to).SumAsync(x => x.ValeurObjectif);
 property2 = await GetObjectivesQueryable(ObjectiveType.Company, new DateTime(DateTime.Now.Year, 1, 1), new DateTime(DateTime.Now.Year, 12, DateTime.DaysInMonth(DateTime.Now.Year, 12)).AddHours(23).AddMinutes(59).AddSeconds(59)).SumAsync(x => x.ValeurObjectif);
}

or the alternative:

foreach (var item in result)
{
 var task1 = GetObjectivesQueryable(ObjectiveType.Company, from, to).SumAsync(x => x.ValeurObjectif);
 var task2 = GetObjectivesQueryable(ObjectiveType.Company, new DateTime(DateTime.Now.Year, 1, 1), new DateTime(DateTime.Now.Year, 12, DateTime.DaysInMonth(DateTime.Now.Year, 12)).AddHours(23).AddMinutes(59).AddSeconds(59)).SumAsync(x => x.ValeurObjectif);
 await Task.WhenAll(task1, task2);
 property1 = task1.Result;
 property2 = task2.Result;
}

From what i understand about async programming the first example above will execute the first instruction, block the execution thread until it complete with the await keyword then fill the property. Then redoing this step for the second property.

At the opposite the second example will asynchronously execute the both task and block the execution thread during the WhenAll instruction, then when both of the tasks are completed it will synchronously set property 1 and property 2.

So From my conclusion in this use case the second example is more performing.

Do my knowledge about async in this case is right?

Thanks in advance.

Mathieu Guindon
71.5k8 gold badges113 silver badges250 bronze badges
asked Jul 21, 2022 at 16:20
6
  • 3
    "block the execution thread until it complete" - exactly not. That would be synchronous behavior. The Thread will be freed to do something else. But the second Task will only be started after the first completed. So it "looks" kind of synchronous. Commented Jul 21, 2022 at 16:25
  • 4
    "the second example will asynchronously execute the both task and block the execution thread" - again: exactly not. "Do my knowledge about async in this case is right?" - I am afraid not. I would recommend Stephen Cleary's Blog. I learnt a lot from it when starting with async. Commented Jul 21, 2022 at 16:28
  • 1
    Thanks for the shared link i will read a bit this evening. Commented Jul 21, 2022 at 16:42
  • You're welcome. It really can be a confusing topic and you'll need your time to wrap your head around it. But take your time - once you get it a new world will open up to you. Commented Jul 21, 2022 at 16:43
  • async/await doesn't block executive tread. It frees the tread and backs it to the thread pool so this tread can be reused by someone else in the time when await operation (some kind of I/O, 3rd party HTTP connections, etc). After await operation is finished, with the magic of the Async state machine, the code flow can be continued in another free thread from a thread pool Commented Jul 21, 2022 at 16:49

2 Answers 2

1

Despite being imprecise about the thread being blocked (which is incorrect as pointed out in the comments), you are correct.

While 'more performing' may mean many things, assuming that both operations are independent, Task.WhenAll option will finish earlier.

Having

var work1 = async () => await Task.Delay(1000);
var work2 = async () => await Task.Delay(2000);
await work1();
await work2();

will take 3 seconds, and

await Task.WhenAll(work1(), work2());

will take 2 seconds.

answered Jul 23, 2022 at 8:39
Sign up to request clarification or add additional context in comments.

3 Comments

"assuming that both operations are independent" -- That's not the only assumption that has to be made. The operations must also be genuinely asynchronous. Specifically the work1() invocation should return an incomplete Task, not a task with .IsCompleted == true.
As always a valid point @TheodorZoulias. Thanks. A good comment with no upvote signals not much value in the answer; can I improve?
Tymtam TBH I don't know. The question is lacking details. Listing all the assumptions that have to be made, so that the second example is more performing, could result in an overly long and boring answer. :-)
0

First point I would suggest is to differentiate between multithreading and multiprocessing. Read here https://towardsdatascience.com/multithreading-and-multiprocessing-in-10-minutes-20d9b3c6a867 to understand more about it.

You are using language provided constructs to make it possible for the OS to process two units of work in parallel. Please do not call it multi-threading, although it is relevant it implies you are in control of lot more factors than you can in parallel processing constructs like async and await. In fact, this is why we still have explicit constructs for threading present in c#, such as BackgroundWorkerThread, despite of success of async and await.

Largely your understanding is correct. However it becomes accurate when you put underlying hardware into picture.

Modern processors have multiple cores. Which means it is much more convenient to have parallelly running units of work. When you write your code using async and await, not necessarily it is going to get processed in parallel. It depends upon lots of other factors including operating system's state, number of threads in the pool, available cores that can pick up subsequent task, other processes running in parallel etc.

If you run async code on a processor which has only one core available for processing, effectively you are running blocking code since there is simply now way to have multiple instructions run in parallel without incurring cost of suspending one thread and loading another into memory - it might in fact become much slower than a simple blocking code that does not require context switching.

With async and await you are simply paving way for multiprocessing if everything else aligns. In most of the circumstances it does, but it has limits.

Take a look at https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/configure-the-max-degree-of-parallelism-server-configuration-option?view=sql-server-ver16 to understand about maximum degree of parallelism.

Also, this is not a new concept. Its the c# language construct that abstracts away underlying complexity, without having you to do it - thats the key aspect of async and await.

answered Jul 21, 2022 at 16:49

2 Comments

Your links are about Python and Sql, not C#!
@PoulBak : Thanks for pointing it out, probably I didnt put it well context, threading and parallelism are OS concepts, language is going to give you way to use it. The reason I posted SQL link was to demonstrate was to show that it existed outside c#'s bounds, i.e. its not about the language.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.