Async-await

Every tutorial on async-await support of C# will state that they are helpers that work like this:

  • an async method is just like ending with an operation completed event being raised;
  • an await method call is just like registering an operation completed event handler, calling the actual operation in a background thread, and eventually the completion event handler runs continuing the original job on the initial thread (i.e. the code after the await statement represents the continuation).

In some way, the behavior for await is similar to yield return, which means waiting with the thread alive until an operation (retrieving the next item in the enumeration, for yield return) completes.

For this mechanism to be useful it’s important that the main thread is able to respond to other events in the meantime, while it’s awaiting for the asynchronous operation to complete. This is usually the case of desktop (or UWP) user interface based applications that have a main thread always running and responding to custom input events (i.e. a Windows application message loop).

However, it’s sometimes hard to fully understand the way async and await work outside of such an environment, so let’s dig in a little bit with a custom console application project that does not have a message loop: let’s build a program that:

  • initializes a data object with a default value;
  • simulates loading another data value from an external system asynchronously (such that the operation is taking at least a few seconds to complete);
  • when the data loading is complete, update the data object;
  • all the time until the end user presses a key, the currently available value from the data object is presented to the user periodically (i.e. every second).

Program.cs source code file would then look like this:

    class Program
    {
        static void Main(string[] args)
        {
            StartLoadingWhilePresentingDataPeriodically();
        }

        private static async void StartLoadingWhilePresentingDataPeriodically()
        {
            // Set up a data object with "not loaded" as initial value.
            var data = new Data { Value = "not loaded" };

            // Creates a thread that will display data value periodically (each second).
            var presenter = new Presenter(data);
            presenter.StartPresentingDataPeriodically();

            // Loader simulates obtaining data value asynchronously (in 2.5 seconds).
            // Until data loading completes, the presenter thread continues to run displaying not loaded value.
            var loader = new Loader();
            data.Value = await loader.LoadDataValueAsync(); // eventually, data value becomes "loaded"

            // The code below runs only after data was loaded.
            Console.WriteLine("Data has been loaded.");

            // Until the user presses a key, the presenter thread continues to run.
            // Of course, by now the presenter thread will display the updated data value.
            Console.ReadKey(true);
            Environment.Exit(0);
        }
    }

Note that the Main method cannot be made async so we needed to extract the code into a different method that is however eventually called synchronously. That’s fine. But inside the extracted StartLoadingWhilePresentingDataPeriodically method you’ll see an await call for loader.LoadDataValueAsync(). This is why the method needed to be async in the first place.

Note that initially data.Value is set to “not loaded”. And the Loader class may actually look like this, returning “loaded” after some time, to replace data.Value content:

    class Loader
    {
        public async Task LoadDataValueAsync()
        {
            // Simulating data loading as a long time asynchronous operation.
            await Task.Delay(2500);

            return "loaded";
        }
    }

However, before data gets loaded, you probably noticed that a presenter object has also been created. That object is responsible for creating a different thread (similar to that of a user interface application’s message loop thread) that periodically prints the current data value:

    class Presenter
    {
        public Presenter(Data data)
        {
            this.data = data;
        }
        private readonly Data data;

        public void StartPresentingDataPeriodically()
        {
            var presenterThread = new Thread(() =>
            {
                while (true)
                {
                    Thread.Sleep(1000);
                    PresentData();
                }
            });
            presenterThread.Start();
        }

        private void PresentData()
        {
            Console.WriteLine("{0:T} - Data: {1}", DateTime.Now, data?.Value);
        }
    }

That’s all; dig the code yourself, and I think you’ll eventually understand a lot more about async and await. For your convenience, here is the output of the console application at runtime:

AsyncDemo-screenshot

Advertisements

About Sorin Dolha

My passion is software development, but I also like physics.
This entry was posted in .NET, C# and tagged , , , , . Bookmark the permalink.

Add a reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s