Click here to Skip to main content
Click here to Skip to main content

Tagged as

WPF with Asynchrony: Part 1

, 11 Sep 2012
Rate this:
Please Sign up or sign in to vote.
This article is about the new features added in C# 5.0 called “Asynchrony” and how we can use them to write asynchronous code which looks like synchronous code.

Introduction

This article is about the new features added in C# 5.0 called “Asynchrony” and how we can use them to write asynchronous code which looks like synchronous code. As we know, WPF applications run on the STA (Single Threaded Apartment) model. The thread which controls the UI is commonly known as the UI Thread. If we want to perform some long running tasks then we need to use Thread or BackGroundWorker and use Dispatcher to update the UI. This article will cover how we can achieve this complexity using Asynchrony with ease. 

Background

For better understanding of this article I would recommend reading on the requirements of Dispatcher, multithreading, and UI updates from a different thread in WPF. It also requires the knowledge of the Task class from the Task Parallel Library. It requires Visual Studio 2012 and .NET Framework 4.5.

Using the code

First of all let’s take an example of an application form .NET 4.0 where we need to perform some long running task on a different thread and need to update the UI.

UI:
<StackPanel>
    <Button Content="Service Call" Click="ServiceCall_Click" />
    <ListView ItemsSource="{Binding Tests}" />
</StackPanel>
Code:
public delegate void UpdateUI(string message);

/// <summary>
/// This the button click event for ServiceCall button on UI which performs              
/// the long running task and updated the UI.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ServiceCall_Click(object sender, RoutedEventArgs e)
{
    Thread asycnWork = new Thread(new ThreadStart(ServiceCall));
    asycnWork.Start();
}

/// <summary>
/// A long running service call.
/// </summary>
private void ServiceCall()
{
    // Consider the below line as a service call which takes some time.
    Thread.Sleep(2000);

    // Update the UI.
    Dispatcher.BeginInvoke(
          new UpdateUI(this.AddToTestsCollection),
        new object[] {   System.Threading.Thread.CurrentThread.ManagedThreadId.ToString()}
    );
}

/// <summary>
/// Add the message to the collection
/// </summary>
/// <param name="message"></param>
private void AddToTestsCollection(string message)
{
    Tests.Add(message);
}

As we can see, we need to create a new thread and have to marshal back to the UI every time we want to update the UI.

Let’s see the new approach with Asycn – Await

/// <summary>
/// Service call button click event
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ServiceCall_Click(object sender, RoutedEventArgs e)
{
    ServiceCallAsycn();
}

/// <summary>
/// Long running service calls
/// We will use for loop to see that all the calls are made on the same thread
/// </summary>
/// <param name="items"></param>
private async void ServiceCallAsycn()
{
    for (int i = 0; i < 5; i++)
    {
        // Service call
        var s = await GetTestAsync(i);

        // Update the UI
        Tests.Add(s);
    }
}

/// <summary>
/// Service call
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
async Task<string> GetTestAsync(int i)
{
    await Task.Delay(2000);
    return i.ToString() + " Call - " + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString();
}

Let us understand the “async” and “await” keywords and their responsibilities.

Async: It just denotes that the method is asynchronous and it has one or more await inside the method. If we don’t use any await in the method, it will give us the warning that the method will work synchronously.

Await: The await operator is applied to a task in an asynchronous method to suspend the execution of the method until the awaited task completes. The task represents ongoing work.

The following sentence is the heart of Asynchrony:

An await expression does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Control then returns to the caller of the async method. When the task completes, it invokes its continuation, and execution of the async method resumes where it left off.

Let us understand this sentence from our example:

When the call encounters await GetTestAsync(i), it will return the control back to the UI. After 2 seconds it will add the result to the Items which will become available on the UI. Here you can see that we don’t need to use Dispatcher’s BeginInvoke or TaskSchedular.FromCurrentSynchronizationContext(). Moreover, if we run the code we will see that all the results show the same thread and hence it does not introduce any new thread itself.

Conclusion

To sum up, “Asynchrony” makes the code very much simple and looks like synchronous code. Moreover it does not introduce any new thread itself. I will try to cover exception handling and more complex scenarios in part 2. Keep learning!!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Bhavik Barot

India India
No Biography provided

Comments and Discussions

 
SuggestionBut if I still on VS 2010 with Framework 4.0? PinmemberCoddioz24-Nov-12 3:02 
GeneralRe: But if I still on VS 2010 with Framework 4.0? Pinmembernelsonfsr22-Mar-13 1:50 
GeneralMy vote of 5 PinmemberCarsten V2.011-Sep-12 18:41 
GeneralRe: My vote of 5 PinmemberBhavik Barot11-Sep-12 19:26 
GeneralRe: My vote of 5 PinmemberCarsten V2.012-Sep-12 9:45 

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

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

| Advertise | Privacy | Mobile
Web03 | 2.8.140827.1 | Last Updated 11 Sep 2012
Article Copyright 2012 by Bhavik Barot
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid