Asynchronous Programming With C#

C# supports both synchronous and asynchronous methods. Let's learn the difference between synchronous and asynchronous and how to code in C#.
 
Interestingly enough, any method we normally create in C# is synchronous by default. For example, the following method fetches data from a database and binds it to a TextBox synchronously.
  1. private void LoadData() {  
  2.         // Create connection  
  3.         SqlConnection conn = new SqlConnection(@ "network address= .; integrated   
  4.             security = true; database = EmployeeDb ");  
  5.             // Create command  
  6.             string sql = @ "select EmpId,Name  
  7.             from dbo.EmployeeDetails where EmpID <= 500 ";  
  8.             // Data binding code goes here  
  9.             try {  
  10.                 // Open connection  
  11.                 conn.Open();  
  12.                 // Execute query via ExecuteReader  
  13.                 SqlDataReader rdr = cmd.ExecuteReader();  
  14.                 while (rdr.Read()) {  
  15.                     txtReader.AppendText("\nEmpID: ");  
  16.                     txtReader.AppendText(rdr.GetValue(1) + "\t\t" + rdr.GetValue(0));  
  17.                     txtReader.AppendText("\n");  
  18.                 }  
  19.             } catch (SqlException ex) {  
  20.                 MessageBox.Show(ex.Message + ex.StackTrace, "Exception Details");  
  21.             } finally {  
  22.                 conn.Close();  
  23.             }  
  24.         }  

What is Synchronous

  • Synchronous represents a set of activities that starts happening together at the same time.
  • A synchronous call waits for the method to complete before continuing with program flow.
How bad is it?
  • It badly impacts the UI that has just one thread to run its entire user interface code.
  • Synchronous behavior leaves end users with a bad user experience and a blocked UI whenever the user attempts to perform some lengthy (time-consuming) operation.

Business Scenario and Problem Statement


Consider a real-world business case in which a UI binds data to the data grid by fetching it from the database. While data is being fetched and bound to the grid the rest of the UI is blocked. Any attempt of interaction with other UI controls will not be evident until the data loading is over. This UI blockage gets over when data fetch-and-binding is completely done. Refer to "Figure 1-1 Synchronous Behavior" below

Synchronous-Behavior.jpg
Figure 1-1 Synchronous Behavior

Solution to the Synchronous Problem


A synchronous method call can create a delay in program execution that causes a bad user experience. Hence, an asynchronous approach (threads) will be better. An asynchronous method call (cretion of a thread) will return immediately so that the program can perform other operations while the called method completes its work in certain situations.

The asynchronous method's behavior is different than synchronous ones because an asynchronous method is a separate thread. You create the thread; the thread starts executing, but control is immediately returned back to the thread that called them time; while the other thread continues to execute.

In general, asynchronous programming makes sense in two cases as,
  • If you are creating a UI intensive application in which the user experience is the prime concern. In this case, an asynchronous call allows the user interface to remain responsive. Unlike as shown in Figure 1-1.
  • If you have other complex or expensive computational work to do, you can continue; interacting with the application UI while wait for the response back from the long-running task.

Asynchronous Patterns


There are various ways to use threads in applications. These recipes are known as Patterns.

Asynchronous Programming Model Pattern
  • Relies on two corresponding methods to represent an asynchronous operation: BeginMethodName and EndMethodName
  • Most often you must have seen this while using delegates or method invocation from a Web Service.
APM-Pattern.jpg
Figure 1-2 APM Pattern

Event Based Asynchronous Pattern
  • The Event-based Asynchronous Pattern has a single MethodNameAsync method and a corresponding MethodNameCompleted event
  • Basically, this pattern enforces a pair of methods and an event to collaborate and help the application execute a thread asynchronously
Event-Based-Pattern.jpg
Figure 1-3 Event Based Pattern

Task based Asynchronous Pattern
  • The Microsoft .NET Framework 4.0 introduces a new Task Parallel Library (TPL) for parallel computing and asynchronous programming. The namespace is "System.Threading.Tasks".
  • A Task can represent an asynchronous operation and a Task provides an abstraction over creating and pooling threads.
Task-Based-Pattern.jpg
Figure 1-4 Task Based Pattern

C# 5.0 async and await based Asynchronous Pattern

  • Two new keywords, async and await, were introduced in C# 5.0 and .NET 4.5. These are implemented at the compiler level and built on top of the "System.Threading.Tasks.Task" feature of .NET 4.0.
  • To work with async and await, you must have Visual Studio 2012
  1. async void LoadEmployee_Click(object sender, RoutedEventArgs e) {  
  2.     // ...  
  3.     await viewer.LoadEmplployeeAsync();  
  4.     // ...  
  5. }  
Problem with older Asynchrnous Patterns

With earlier patterns, the programmer needed to do all the plumbing and collaboration between a pair of methods (BeginMethod and EndMethod) or a method and an event (MethodAsync and MethodCompleted) to make them functional; see Figure 1-2 APM Pattern. This approach was a tedious job not only in terms of syntax but also from sequence of statements inside the method body.

C# 5.0 async/await offers a completely different and easy way to do asynchronous programming. With this feature it's no longer the responsibility of the programmer to do the syntax related tedious work, rather this is now done by the keywords (C# 5.0 async / await) provided by the programming language.

As a result, asynchronous code is easy to implement and retain its logical structure. Hence now it is as easy as writing your normal method without concern of any extra plumbing and so on. As shown in other asynchronous patterns in which you need to deal with a pair of methods or a combination of methods and events and so on.

Business Scenario

Consider a real-world business case, a WPF UI binding data to the data grid by fetching a large number of rows from a database. While data is being fetched and bound to a grid, the rest of the UI should continue to be responsive. Any attempt at interaction with other UI controls must not be blocked and data loading and binding must continue in parallel.. Refer to "Figure 1-1 Synchronous Behavior" below.

Asynchronous-Behavior.jpg
Figure 1-5 Asynchronous Behavior

Let's Code

If you look at the code below, it looks like normal code as shown at the very beginning of this article. The differences worth noting are highlighted in yellow in the code block below.
  1. Private async void LoadCustomersAsync() {  
  2.     using(EmployeeDbEntities ent = new EmployeeDbEntities()) {  
  3.         IdbConnection conn = (ent.Connection as EntityConnection).StoreConnection;  
  4.         conn.Open();  
  5.         using(DbCommand cmd = (DbCommand) conn.CreateCommand()) {  
  6.             var query = from p in ent.EmployeeDetails  
  7.             where p.Name.Contains("FN") && p.SurName.Contains("SN") && (p.Name + p.SurName).Length > 3  
  8.             select p;  
  9.             //Convert linq query to SQL statement for CommandText  
  10.             string str = ((ObjectQuery) query).ToTraceString();  
  11.             cmd.CommandText = str;  
  12.             // Invoke Async flavor of ExecuteReader  
  13.             var task = await cmd.ExecuteReaderAsync();  
  14.             //translate retieved data to entity customer   
  15.             var cust1 = await Task.Run(  
  16.                 () => ent.Translate < EmployeeDetails > (task).ToList < EmployeeDetails > ());  
  17.             employeesDataGrid.ItemsSource = cust1;  
  18.         }  
  19.     }  
  20. }  
As you noticed, the flow looks very natural and no extra plumbing appears in the code. Except async/await, task and of course the asynchronous flavor of the main function that is retrieving data from the database; in our case, ExecuteReaderAsync() is the method.

This code will allow you to perform UI interaction; when data is being fetched and grid binding is taking place, refer to the Figure 1-6 async/await in action.

async-await-in-Action.jpg
Figure 1-6 async/await in action (as you can see in image 36K + rows pulled)

Legacy Operations

Microsoft suggests that with the release of .NET 4.5, the following commonly used methods should be considered as legacy operations. When possible and if you are usng .NET 4.5 then you must use async and await to do asynchronous programming in your application.

Legacy-Operations.jpg
Figure 1-7 Legacy Operations

What if you don't have Visual Studio 2012

Since Visual Studio 2012 is still not adopted by many development teams in various organizations and many developers still use Visual Studio 2010. So, can they use async and await syntax there?

Microsoft released an async CTP that is supposed to work well with Visual Studio 2010 (without SP1) and allow the developers to use the same syntax.

Search for "async CTP" in Bing or Google.

Async-CTP-download-page.jpg
Figure 1-8 Async CTP download page

Side-by-Side Comparison of various ways techniques

Side-by-Side-comparison-on-various-techniques.jpg
Figure 1-9 Side-by-Side comparison on various techniques
Author
Vidya Vrat Agarwal
0 28.6k 12.3m
Next » C# Asynchronous Programming - Async and Await