Bartosz
Bartosz

Reputation: 4592

Trying to understand async/await in c#

I have written a method using async keyword, but cannot understand the outcome of it, and the reason it doesn't really work:

static async void ExampleWithValueReturned_Async(Stopwatch sw, SlowOperation opr1, SlowOperation opr2)
{
    Console.WriteLine("Started processing ASYNC. Start: {0}", sw.Elapsed);
    sw.Start();

    Console.WriteLine("2 Step0: {0}", sw.Elapsed);
    var sum1_2 = await Task<double>.Factory.StartNew(() => opr1.PerformSlowOperation(1, true));
    Console.WriteLine("2 Step1: {0}", sw.Elapsed);
    var sum2_2 = await Task<double>.Factory.StartNew(() => opr2.PerformSlowOperation(1, true));
    Console.WriteLine("2 Step2: {0}", sw.Elapsed);

    Console.WriteLine("Operation 1 gave sum: {0}", sum1_2.ToString("0.##"));
    Console.WriteLine("Operation 2 gave sum: {0}", sum2_2.ToString("0.##"));
    Console.WriteLine("Stopped processing ASYNC. Stop: {0}", sw.Elapsed);
    sw.Stop();

    sw.Reset();
    Console.WriteLine("");
}

I was expecting this to run around twice as fast as inline processing, since PerformSlowOperation would run in parallel. My expectation was that producing sum1_2 and sum2_2 will be happening at the same time, while analysis of the outcome, based on Stopwatch logs, shows that both values are processed in exactly the same way as in the inline processing case. Overall time is also the same in both cases. Why is it so?

Upvotes: 1

Views: 95

Answers (1)

Gabriel Sadaka
Gabriel Sadaka

Reputation: 1746

The C# await keyword does exactly what the word says, it waits for the function to finish executing before proceeding to the next line. If you didn't use the await keyword then it will run in the background and continue executing the rest of the code, however this doesn't allow you to do anything with the results.

To run both of the tasks in parallel you will need to explicitly state to wait for all of the tasks to finish before continuing rather than just waiting for each one.

Task t1 = Task<double>.Factory.StartNew(() => opr1.PerformSlowOperation(1, true));
Task t2 = Task<double>.Factory.StartNew(() => opr2.PerformSlowOperation(1, true));
await Task.WhenAll(t1,t2);
var sum1_2 = t1.Result;
var sum2_2 = t2.Result;

The above code will wait until both finish, running them in parallel before continuing with the rest of the code.

The reason the keyword exists is not to enable parallel tasks, it is to enable applications to wait for a single asynchronous method to finish before executing the rest of the code. It is very useful in ASP.NET where a long running task will hold up threads wastefully, using await tells ASP.NET that it can give up the control of the thread to another request until the long running request of the previous task finishes then when it does finish give it back control of the thread.

Upvotes: 5

Related Questions