Creating an async method

The TAP is a new pattern for asynchronous programming in .NET Framework 4.5. It is based on a task, but in this case a task doesn't represent work which will be performed on another thread. In this case, a task is used to represent arbitrary asynchronous operations.

Let's start learning how async and await work by creating a Windows Presentation Foundation (WPF) application that accesses the web using HttpClient. This kind of network access is ideal for seeing TAP in action. The application will get the contents of a classic book from the web, and will provide a count of the number of words in the book.

How to do it…

Let's go to Visual Studio 2012 and see how to use the async and await keywords to maintain a responsive UI by doing the web communications asynchronously.

  1. Start a new project using the WPF Application project template and assign WordCountAsync as Solution name.
  2. Begin by opening MainWindow.xaml and adding the following XAML to create a simple user interface containing Button and TextBlock:
    <Window x:Class="WordCountAsync.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="WordCountAsync" Height="350" Width="525">
        <Grid>
            <Button x:Name="StartButton" 
        Content="Start" 
        HorizontalAlignment="Left" 
        Margin="219,195,0,0" 
        VerticalAlignment="Top" 
        Width="75" 
        RenderTransformOrigin="-0.2,0.45" 
        Click="StartButton_Click"/>
            <TextBlock x:Name="TextResults" 
          HorizontalAlignment="Left" 
          Margin="60,28,0,0" 
          TextWrapping="Wrap" 
          VerticalAlignment="Top" 
          Height="139" 
          Width="411"/>
    
        </Grid>
    </Window>
    How to do it…
  3. Next, open up MainWindow.xaml.cs. Go to the Project and add a reference to System.Net.Http.
  4. Add the following using directives to the top of your MainWindow class:
    using System;
    using System.Linq;
    using System.Net.Http;
    using System.Threading.Tasks;
    using System.Windows;
  5. At the top of the MainWindow class, add a character array constant that will be used to split the contents of the book into a word array.
    char[] delimiters = { ' ', ',', '.', ';', ':', '-', '_', '/', 'u000A' };
  6. Add a button click event for the StartButton and add the async modifier to the method signature to indicate that this will be a async method. Please note that async methods that return void are normally only used for event handlers, and should be avoided.
    private async void StartButton_Click(object sender, RoutedEventArgs e)
    {
      
    }
  7. Next, let's create a async method called GetWordCountAsync that returns Task<int>. This method will create HttpClient and call its GetStringAsync method to download the book contents as a string. It will then use the Split method to split the string into a wordArray. We can return the count of the wordArray as our return value.
    public async Task<int> GetWordCountAsync()
    {
      TextResults.Text += "Getting the word count for Origin of Species...
    ";
      var client = new HttpClient();
      var bookContents = await client.GetStringAsync(@"http://www.gutenberg.org/files/2009/2009.txt");
      var wordArray = bookContents.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
      return wordArray.Count();           
    }
  8. Finally, let's complete the implementation of our button click event. The Click event handler will just call GetWordCountAsync with the await keyword and display the results to TextBlock.
    private async void StartButton_Click(object sender, RoutedEventArgs e)
    {
      var result = await GetWordCountAsync();
      TextResults.Text += String.Format("Origin of Species word count: {0}",result);
    }
  9. In Visual Studio 2012, press F5 to run the project. Click on the Start button, and your application should appear as shown in the following screenshot:
    How to do it…

How it works…

In the TAP, asynchronous methods are marked with an async modifier. The async modifier on a method does not mean that the method will be scheduled to run asynchronously on a worker thread. It means that the method contains control flow that involves waiting for the result of an asynchronous operation, and will be rewritten by the compiler to ensure that the asynchronous operation can resume this method at the right spot.

Let me try to put this a little more simply. When you add the async modifier to a method, it indicates that the method will wait on an asynchronous code to complete. This is done with the await keyword. The compiler actually takes the code that follows the await keyword in an async method and turns it into a continuation that will run after the result of the async operation is available. In the meantime, the method is suspended, and control returns to the method's caller.

If you add the async modifier to a method, and then don't await anything, it won't cause an error. The method will simply run synchronously.

An async method can have one of the three return types: void, Task, or Task<TResult>. As mentioned before, a task in this context doesn't mean that this is something that will execute on a separate thread. In this case, task is just a container for the asynchronous work, and in the case of Task<TResult>, it is a promise that a result value of type TResult will show up after the asynchronous operation completes.

In our application, we use the async keyword to mark the button click event handler as asynchronous, and then we wait for the GetWordCountAsync method to complete by using the wait keyword.

private async void StartButton_Click(object sender, RoutedEventArgs e)
{
  StartButton.Enabled = false;
  var result = await GetWordCountAsync();
  TextResults.Text += String.Format("Origin of Species word count: {0}",
..................  result);
  StartButton.Enabled = true;
}

The code that follows the await keyword, in this case, the same line of code that updates TextBlock, is turned by the compiler into a continuation that will run after the integer result is available.

If the Click event is fired again while this asynchronous task is in progress, another asynchronous task is created and awaited. To prevent this, it is a common practice to disable the button that is clicked.

It is a convention to name an asynchronous method with an Async postfix, as we have done with GetWordCountAsync.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.48.62