You can avoid performance bottlenecks and enhance the overall responsiveness of your application by using asynchronous programming. However, traditional techniques for writing asynchronous applications can be complicated, making them difficult to write, debug, and maintain.
Visual Studio 2012 introduces a simplified approach, async programming, that leverages 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. As a result, you get all the advantages of asynchronous programming with a fraction of the effort.
Asynchrony is essential for activities that are potentially blocking, such as when your application accesses the web. Access to a web resource sometimes is slow or delayed. If such an activity is blocked within a synchronous process, the entire application must wait. In an asynchronous process, the application can continue with other work that doesn’t depend on the web resource until the potentially blocking task finishes.
Asynchrony proves especially valuable for applications that access the UI thread because all UI-related activity usually shares one thread. If any process is blocked in a synchronous application, all are blocked. Your application stops responding, and you might conclude that it has failed when instead it’s just waiting.
When you use asynchronous methods, the application continues to respond to the UI. You can resize or minimize a window, for example, or you can close the application if you don’t want to wait for it to finish.
The Async and Await keywords in Visual Basic and the async and await keywords in C# are the heart of async programming. By using those two keywords, you can use resources in the .NET Framework or the Windows Runtime to create an asynchronous method almost as easily as you create a synchronous method. Asynchronous methods that you define by using async and await are referred to as async methods.
The following example shows an async method.
- // Three things to note in the signature:
- // - The method has an async modifier.
- // - The return type is Task or Task<T>. (See "Return Types" section.)
- // Here, it is Task<int> because the return statement returns an integer.
- // - The method name ends in "Async."
- async Task<int> AccessTheWebAsync()
- {
- // You need to add a reference to System.Net.Http to declare client.
- HttpClient client = new HttpClient();
- // GetStringAsync returns a Task<string>. That means that when you await the
- // task you'll get a string (urlContents).
- Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
- // You can do work here that doesn't rely on the string from GetStringAsync.
- DoIndependentWork();
- // The await operator suspends AccessTheWebAsync.
- // - AccessTheWebAsync can't continue until getStringTask is complete.
- // - Meanwhile, control returns to the caller of AccessTheWebAsync.
- // - Control resumes here when getStringTask is complete.
- // - The await operator then retrieves the string result from getStringTask.
- string urlContents = await getStringTask;
- // The return statement specifies an integer result.
- // Any methods that are awaiting AccessTheWebAsync retrieve the length value.
- return urlContents.Length;
- }
If AccessTheWebAsync doesn’t have any work that it can do between calling GetStringAsync and awaiting its completion, you can simplify your code by calling and awaiting in the following single statement.
- string urlContents = await client.GetStringAsync();
The following characteristics summarize what makes the previous example an async method.
- The method signature includes an Async or async modifier.
- The name of an async method, by convention, ends with an “Async” suffix.
- Task<TResult> if your method has a return statement in which the operand has type TResult.
- Task if your method has no return statement or has a return statement with no operand.
- Void (a Sub in Visual Basic) if you’re writing an async event handler.The return type is one of the following types:
- The method usually includes at least one await expression, which marks a point where the method can’t continue until the awaited asynchronous operation is complete. In the meantime, the method is suspended, and control returns to the method’s caller. The next section of this topic illustrates what happens at the suspension point.
In async methods, you use the provided keywords and types to indicate what you want to do, and the compiler does the rest, including keeping track of what must happen when control returns to an await point in a suspended method. Some routine processes, such as loops and exception handling, can be difficult to handle in traditional asynchronous code. In an async method, you write these elements much as you would in a synchronous solution, and the problem is solved.
The most important thing to understand in asynchronous programming is how the control flow moves from method to method. The following diagram leads you through the process.
he numbers in the diagram correspond to the following steps.
- An event handler calls and awaits the AccessTheWebAsync async method.
- AccessTheWebAsync creates an HttpClient instance and calls the GetStringAsync asynchronous method to download the contents of a website as a string.
- Something happens in GetStringAsync that suspends its progress. Perhaps it must wait for a website to download or some other blocking activity. To avoid blocking resources, GetStringAsync yields control to its caller,AccessTheWebAsync.GetStringAsync returns a Task<TResult> where TResult is a string, and AccessTheWebAsync assigns the task to thegetStringTaskvariable. The task represents the ongoing process for the call to GetStringAsync, with a commitment to produce an actual string value when the work is complete.
- Because getStringTask hasn’t been awaited yet, AccessTheWebAsync can continue with other work that doesn’t depend on the final result from GetStringAsync. That work is represented by a call to the synchronous methodDoIndependentWork.
- DoIndependentWork is a synchronous method that does its work and returns to its caller.
- AccessTheWebAsync has run out of work that it can do without a result from getStringTask. AccessTheWebAsyncnext wants to calculate and return the length of the downloaded string, but the method can’t calculate that value until the method has the string.Therefore, AccessTheWebAsync uses an await operator to suspend its progress and to yield control to the method that calledAccessTheWebAsync. AccessTheWebAsync returns a Task(Of Integer) or Task<int> to the caller. The task represents a promise to produce an integer result that’s the length of the downloaded string.
- Inside the caller (the event handler in this example), the processing pattern continues. The caller might do other work that doesn’t depend on the result from AccessTheWebAsync before awaiting that result, or the caller might await immediately. The event handler is waiting forAccessTheWebAsync, and AccessTheWebAsync is waiting for GetStringAsync.
- GetStringAsync completes and produces a string result. The string result isn’t returned by the call toGetStringAsync in the way that you might expect. (Remember that the method already returned a task in step 3.) Instead, the string result is stored in the task that represents the completion of the method, getStringTask. The await operator retrieves the result from getStringTask. The assignment statement assigns the retrieved result to urlContents.
- When AccessTheWebAsync has the string result, the method can calculate the length of the string. Then the work of AccessTheWebAsync is also complete, and the waiting event handler can resume. In the full example at the end of the topic, you can confirm that the event handler retrieves and prints the value of the length result.
If you are new to asynchronous programming, take a minute to consider the difference between synchronous and asynchronous behavior. A synchronous method returns when its work is complete (step 5), but an async method returns a task value when its work is suspended (steps 3 and 6). When the async method eventually completes its work, the task is marked as completed and the result, if any, is stored in the task.
Note :- If GetStringAsync (and therefore getStringTask) is complete before AccessTheWebAsync awaits it, control remains inAccessTheWebAsync. The expense of suspending and then returning to AccessTheWebAsync would be wasted if the called asynchronous process (getStringTask) has already completed and AccessTheWebSync doesn’t have to wait for the final result.
If you specify that a method is an async method by using an Async or async modifier, you enable the following two capabilities.
- The marked async method can use Await or await to designate suspension points. The await operator tells the compiler that the async method can’t continue past that point until the awaited asynchronous process is complete. In the meantime, control returns to the caller of the async method.The suspension of an async method at an await expression doesn’t constitute an exit from the method, and finallyblocks don’t run.
- The marked async method can itself be awaited by methods that call it.
An async method typically contains one or more occurrences of an await operator, but the absence of await expressions doesn’t cause a compiler error. If an async method doesn’t use an await operator to mark a suspension point, the method executes as a synchronous method does, despite the async modifier. The compiler issues a warning for such methods.
In .NET Framework programming, an async method typically returns a Task or a Task<TResult>. Inside an async method, an await operator is applied to a task that’s returned from a call to another async method.
You specify Task<TResult> as the return type if the method contains a Return (Visual Basic) or return (C#) statement that specifies an operand of type TResult.
You use Task as the return type if the method has no return statement or has a return statement that doesn’t return an operand.
An async method that’s a Sub procedure or that has a void return type can’t be awaited, and the caller of a void-returning method can’t catch any exceptions that the method throws.
An async method can’t declare ByRef parameters in Visual Basic or ref or out parameters in C#, but the method can call methods that have such parameters.
By convention, you append “Async” to the names of methods that have an Async or async modifier.
Comments
Post a Comment