C# – Smooth as Peanut Butter: Multi-Threading with Async and Await

The .NET framework makes multi-threading as easy as opening a can of peanut butter. Let’s make a small project to demonstrate.

Create a new C# WPF project in Visual Studio, and name it anything you like.

Drag a label and textbox on the mainwindow. Name the label “lblTime”.

Your XAML should looke something like below:


<Window x:Class="Butter.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Label x:Name="lblTime" Content="Label" HorizontalAlignment="Center" Margin="10,10,0,0" VerticalAlignment="Top"  Width="497"/>
        <TextBox x:Name="txtText" HorizontalAlignment="Left" Height="232" Margin="15,77,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="492"/>
    </Grid>
</Window>

Enter the following code in MainWindow.xaml.cs:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Butter
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            
            getTime();
        }
   
        private async void getTime(){
            
            Task task = Task.Run<string>(() => {

                System.Threading.Thread.Sleep(1000);
                return DateTime.Now.ToString();

            });

            lblTime.Content = await task;
            getTime();

        }
    }
}

Run the program. What happens? The time is displayed and updated every second. In the meanwhile you can type text in the textbox without being disturbed.

By making the method getTime async, it runs in another thread than the User Interface. Let’s analyse what’s happening in that method.

An async method needs a Task. We make one that returns a string. We invoke it with a lambda (the ()=>{} thing).

The task sleeps for a second and returns the current time.

Next, we tell the content property of the label to await the task.

What happens there? Well, the code in this method stops. Anything after the await will not be executed until the task is ready and returns a value.

In the meanwhile your program continues working. You achieved that by making the method async.

When ready, the task returns a string. The label content has been waiting for that string, and only when that string is received by the label, the rest of the code in the method is executed.

And te rest of the code… invokes the method again.

Leave a Reply