Click here to Skip to main content
15,867,756 members
Articles / Desktop Programming / WPF

Building Responsive UI using Async Await in C#

Rate me:
Please Sign up or sign in to vote.
3.50/5 (5 votes)
20 Sep 2015CC (ASA 3U)3 min read 16.4K   7   6
Why build responsive UI? Answer seems obvious that end-user should experience that application doesn’t hang often (for developers POV, a time taking background operation makes it look like hanging). So lets learn building responsive UI using Async Await keywords Visual Studio 2012 introduced a

Why build responsive UI? Answer seems obvious that end-user should experience that application doesn’t hang often (for developers POV, a time taking background operation makes it look like hanging). So lets learn building responsive UI using Async Await keywords

Visual Studio 2012 introduced a simplified approach, async programming, that leverage asynchronous support in the .NET Framework 4.5 and the Windows Runtime. The compiler does the difficult work that the developer used to do, and your application retains a logical structure that resembles synchronous code. This is extract from MSDN

Source Code was in written Visual Studio 2015 Community Edition, WPF, C#, .NET 4.5 on Windows 7 OS. However it can be used with Visual Studio 2013/2012(any version) on Windows 8, Windows 10 also.

Building Responsive UI using Async Await in C#

A simple WPF application which reads 12MB text file, then loops through and returns unique words with count of its occurrences in text file. Instead of using Thread Sleep or HttpClient to demonstrate async await, I have word count kind of example.

Create time taking library “WordCountLib”

  • Create blank solution naming “AsyncAwaitDemoApp”.
  • Create class library naming “WordCountLib” and create C# class file “WordCountClass”.
  • Copy below code containing methods “FindWordCounts” and “FindWordCountsAsync”.

 

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace WordCountLib
{
    public class WordCountClass
    {
        /// 
        /// Reads through the file, generates unique words and its number of occurrences
        /// 
        /// 
        public List FindWordCounts()
        {
            //Ensure that LongFile.txt exists
            var words = Regex.Matches(File.ReadAllText(@"D:\LongFile.txt"), @"\w+").Cast()
            .Select((m, pos) => new { Word = m.Value, Pos = pos })
            .GroupBy(s => s.Word, StringComparer.CurrentCultureIgnoreCase)
            .Select(g => new Words { WordName = g.Key, NoOfOccurance = g.Select(z => z.Pos).Count() })
            .ToList();

            return words;
        }

        /// 
        /// Reads through the file, generates unique words and its number of occurrences using Async and Await
        /// 
        /// 
        public async Task<list> FindWordCountsAsync()
        {
            //Ensure that LongFile.txt exists
            var words = Regex.Matches(File.ReadAllText(@"D:\LongFile.txt"), @"\w+").Cast()
            .Select((m, pos) => new { Word = m.Value, Pos = pos })
            .GroupBy(s => s.Word, StringComparer.CurrentCultureIgnoreCase)
            .Select(g => new Words { WordName = g.Key, NoOfOccurance = g.Select(z => z.Pos).Count() });

            //This is more like Task-Based Asynchronous Pattern
            return await Task.Run(() => words.ToList());           
        }
    }
}

 

  • Create C# class “Words”. This is POCO class to hold words name and its occurrences. Copy below

 

namespace WordCountLib
{
    public class Words
    {
        public string WordName { get; set; }
        public int NoOfOccurance { get; set; }
    }
}

 

  • LongFile.txt contains text copied from http://norvig.com/big.txt ; I have copied all text twice so that file is 12MB and processing should take time. Ensure that you have file at D:\LongFile.txt or else FileNotFound exception.

Building UI using WPF

  • Create WPF application “WordCount.UI”, add “WordCountLib” assembly reference so that we can call WordCountClass methods.
  • Open MainWindow.xaml and copy below code. This is startup window for our WPF. Draw using toolbar not so elegant but that’s  not needed.

 

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WordCount.UI"
        xmlns:WordCountLib="clr-namespace:WordCountLib;assembly=WordCountLib" x:Class="WordCount.UI.MainWindow"
        mc:Ignorable="d"
        Title="Async Await Demo" Height="600" Width="825" WindowStartupLocation="CenterScreen">
    
        <button>
                
        <label>
        
            
                
                    
                        
                            
                            
                        
                        <label>
                        <label>
                    </label></label>
                
            
        
        
            
                
                    
                        
                            
                            
                        
                        <label>
                        <label>
                    </label></label>
                
            
        
        </label></button><button>

    
</button>

 

  • Open MainWindow.xaml.cs, its code behind file for our start up window. Copy the below code.
    • Method “btndwn_Click” is old school type of button click event handler for “Search Words”, it instantiate “WordCountClass”, calls “FindWordsCounts”, shows listbox and binds a list of words to listbox
    • Method “btndwnasyn_Click” is old school type of button click event handler for “Search Words Async Way”, it instantiate “WordCountClass”, calls “FindWordsCountsAsync”, shows listbox and binds a list of words to listbox. Note that it has async keyword in its method signature and await keyword while “FindWordsCountsAsync”
    • “Log” is very simple method to log information to screen.
  • Build and run it, check out image after it loads screen.

If we carefully see, await keyword is placed in-line while calling “FindWordsCountsAsync”. It clearly indicates this method is time-consuming and will block UI thread.

 

using System;
using System.Windows;
using WordCountLib;

namespace WordCount.UI
{
    /// 
    /// Interaction logic for MainWindow.xaml
    /// 
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        /// 
        /// Button click Synchronous processing
        /// 
        
        private  void btndwn_Click(object sender, RoutedEventArgs e)
        {
            Log("START");
            
            if (listBox.Visibility == Visibility.Visible)
            {
                listBox.Visibility = Visibility.Collapsed;
            }

            WordCountClass wrdSimple = new WordCountClass();            
            var listCount = wrdSimple.FindWordCounts();            
            listBox.Visibility = Visibility.Visible;
            listBoxasync.Visibility = Visibility.Collapsed;
            listBox.ItemsSource = listCount;            
            Log("Done ");
        }
        
        private async void btndwnasyn_Click(object sender, RoutedEventArgs e)
        {
            Log("START Async");
            if (listBoxasync.Visibility == Visibility.Visible)
            {
                listBoxasync.Visibility = Visibility.Collapsed;
            }
            WordCountClass wrdSimple = new WordCountClass();
            var listCount = await wrdSimple.FindWordCountsAsync();
            listBoxasync.Visibility = Visibility.Visible;
            listBox.Visibility = Visibility.Collapsed;
            listBoxasync.ItemsSource = listCount;
            
            Log("Done Async");
        }

        private void Log(string text)
        {
            string line = string.Format("{0:HH:mm:ss.fff}: {1}\r\n", DateTime.Now, text);
            logtxtBlock.AppendText(line);
        }
    }
}

 

asyncAwaitWPF Window

WPF Main Window for Async Await Demo

 

Testing the responsiveness of the WPF UI

  • Click on button “Search Words”, try to move window, resize it. You can’t do anything as it reads the file, finds all words count and binds to list box. This is called non responsive UI or application hanging. Check out GIF image below. Notice that after it loads list box, screen window moves bit because after button click I tried to use window.
async NON responsive

Non Responsive UI on button click

  • Now run application again, click “Search Words Async Way”. Just move around window, resize it, see Log information being written. This called RESPONSIVE UI using Async Await in C#
  • Just play around it by clicking buttons back and forth.
responsive async await

Responsive UI using Async Await

 

  • Async methods are intended to be non-blocking operations. An await expression in an async method doesn’t block the current thread while the awaited task is running.
  • The async and await keywords don’t cause extra threads to be created. Async methods don’t need multi-threading because an async method doesn’t run on its own thread.

The post Building Responsive UI using Async Await in C# appeared first on Mithunvp.com.

License

This article, along with any associated source code and files, is licensed under The Creative Commons Attribution-Share Alike 3.0 Unported License


Written By
India India
I am Mithun Pattankar, a Software Professional on day job and blogger at nights. My interests are in Microsoft Technologies like DotNet, Visual Studio, ASP.NET, WPF, WCF, C#, HTML5

URL: www.mithunvp.com

Comments and Discussions

 
SuggestionPlease visit site link for download Pin
Mithun Pattankar21-Sep-15 19:50
Mithun Pattankar21-Sep-15 19:50 
Question[My vote of 1] No Download Pin
SgtWingHead20-Sep-15 23:41
SgtWingHead20-Sep-15 23:41 
AnswerRe: [My vote of 1] No Download Pin
Mithun Pattankar21-Sep-15 19:50
Mithun Pattankar21-Sep-15 19:50 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.