Vanitas
Vanitas

Reputation: 903

C# Asynchronous Programming

I have my Program.cs file:

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace AsyncTest
{
    class Program
    {

        static async Task Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            var interesting = new InterestingObject();

            List<int> list;
            List<int> alsoList;

            list = await interesting.GenerateListAsync();
            alsoList = interesting.GenerateList();

            Console.WriteLine("Done! :)");

            list    .ForEach(xs => Console.WriteLine(xs));
            alsoList.ForEach(xs => Console.WriteLine (xs));

        }

    }
}

And here's the code for InterestingObject:

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace AsyncTest
{
    public class InterestingObject
    {
        public InterestingObject()
        {
        }

        public List<int> GenerateList()
        {

            Console.WriteLine("Gonna generate the list!");

            var list = new List<int>();
            int i = 0;
            while (i < 5)
            {

                Random random = new Random();
                list.Add(random.Next());
                Console.WriteLine("Generated a new int!");
                VeryHeavyCalculations();

                i++;
            }

            return list;

        }

        public async Task<List<int>> GenerateListAsync()
        {

            Console.WriteLine("Gonna generate the list async!");

            var list = new List<int>();
            int i = 0;
            while (i < 5)
            {

                Random random = new Random();
                list.Add(random.Next ());
                Console.WriteLine("Generated a new int asyncronously!");
                await Task.Run(() => VeryHeavyCalculations());

                i++;
            }

            return list;

        }

        public void VeryHeavyCalculations()
        {
            Thread.Sleep (1000);
        }
    }
}

I expect list = await interesting.GenerateListAsync(); to run asynchronously while alsoList = interesting.GenerateList(); is running, effectively logging the output of GenerateList into my console while GenerateListAsync is doing the exact same, or to see GenerateListAsync finish near-instantly when GenerateList finishes.

However, looking into the console I see my application running GenerateListAsync and then run GenerateList afterwards.

I'm doing this wrong but no source has been sufficient to solve this problem.

Upvotes: 0

Views: 143

Answers (2)

user5877586
user5877586

Reputation:

Further to the answer, have a look at await (C# Reference)

The await operator is applied to a task in an asynchronous method to insert a suspension point in the execution of the method until the awaited task completes. that's the reason in your application running GenerateListAsync and then run GenerateList afterwards. To run the GenerateListAsync asynchronously you need to take the GenerateListAsync return in Task variable and then call GenerateList and after that use await for GenerateListAsync method.

e.g

Task <List<int>> longRunningTask = interesting.GenerateListAsync();
        alsoList = interesting.GenerateList();
        list = await longRunningTask;

Upvotes: 0

Marc Gravell
Marc Gravell

Reputation: 1062780

I expect list = await interesting.GenerateListAsync(); to run asynchronously whilealsoList = interesting.GenerateList(); is running,

That expectation is incorrect; the entire point of await is that it does not continue past that point until the asynchronous operation is complete; it does this with a range of tricks including async state machines that allow an incomplete operation to be resumed when the results come back in. You can, however, just move the point at which you await, so that it doesn't cause this perceived blockage:

List<int> list;
List<int> alsoList;

var pending = interesting.GenerateListAsync(); // no await
alsoList = interesting.GenerateList();
list = await pending; // essentially "joins" at this point... kind of

Note that async and parallelism are different things; they can be used together, but that isn't what happens by default. Note also: not all code is designed to allow concurrent usage, so you shouldn't do this kind of thing without knowing whether it is OK to use concurrent calls on a particular API.

Upvotes: 3

Related Questions