- What's New in C# 6.0 and VB 14
- Language Primer
- Language Features
- Asynchronous Programming
- The .NET Framework
- Summary
Asynchronous Programming
Most of the time, developers write code that processes a series of commands sequentially. For instance, we can envision a simple routine (TallyExpenseReport) that accepts an ID, calls a second routine (GetExpenseReport) to call a service with that ID to retrieve an expense report, grabs the total dollar amount of the expense report, and then updates a database before finally giving the user a message indicating the status of the operation.
C#
public void TallyExpenseReport(string id) { //get the expense report ExpenseReport rpt = GetExpenseReport(id); UpdateDataStore(id, rpt.TotalAmt); } public ExpenseReport GetExpenseReport(string id) { //code to fetch an expense report goes here return new ExpenseReport(); }
VB
Public Sub TallyExpenseReport(id As String) 'get the expense report Dim rpt As ExpenseReport = GetExpenseReport(id) UpdateDataStore(id, rpt.TotalAmt) End Sub Public Function GetExpenseReport(id As String) As ExpenseReport 'code to fetch an expense report goes here Return New ExpenseReport() End Function
But in this top-down sequential process, we have actually sacrificed a bit of the user’s experience; because of its sequential nature, each time we make a call, the application is blocked until the call completes. If we are talking to a service, this might be anywhere from fractions of a second to minutes. The same is true when we go to update the database. The entire time that the application is waiting for a task to complete, the application (and the user) cannot do anything else.
A better approach is an asynchronous one: we still issue a request for information from the service, and we still make a call to update the database, but in this case the application makes the call and then continues on its merry way. That, in essence, is an asynchronous application: the application doesn’t block any of the calls we chose to make asynchronous. These types of applications are fraught with complexity. But even the syntax to create and work with asynchronous calls has been complex and a tad arcane. The .NET Framework 4.5 added two keywords—async and await—to both Visual Basic and C# that help make asynchronous programming a bit easier.
Async is used as a modifier to indicate that a method is asynchronous. The await keyword is used to mark any calls within an async method that should be waited on for completion. For the runtime wiring to work, all your async function calls also need to have their return values modified to Task<originaltype> (C#) or Task(of originaltype).
If we were to take another stab at writing our expense report code, we might end up with two routines that look something like this.
C#
public async void TallyExpenseReport(string id) { //get the expense report ExpenseReport rpt = await GetExpenseReport(id); UpdateDataStore(id, rpt.TotalAmt); } public async Task<ExpenseReport> GetExpenseReport(string id) { //code to fetch an expense report goes here return new ExpenseReport(); }
VB
Public Async Sub TallyExpenseReport(id As String) 'get the expense report Dim rpt As ExpenseReport = Await GetExpenseReport(id) UpdateDataStore(id, rpt.TotalAmt) End Sub Public Async Function GetExpenseReport(id As String) As Threading.Tasks.Task(Of ExpenseReport) 'code to fetch an expense report goes here Return New ExpenseReport() End Function
Our “await” call to GetExpenseReport will cause the TallyExpenseReport routine to block further execution in this method until a value is returned; meanwhile, execution control will be immediately passed back to the original method that called TallyExpenseReport in the first place. In other words, the application will continue on, it won’t block, and it may elect to do other things such as processing more user input, making additional expense report calls, and so on.