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. A simplified approach, async programming, that leverages asynchronous support in the .NET platforms. 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.
C# 5 features require Mono 3.0 that is included in Xamarin.iOS 6.4 and Xamarin.Android 4.8.
async keyword is placed in a method declaration (or on a lambda or anonymous method) to indicate that it contains code that can run asynchronously, ie. not block the caller’s thread.
A method marked with
async should contain at least one await expression or statement. If no
awaits are present in the method then it will run synchronously (the same as if there were no
async modifier). This will also result in a compiler warning (but not an error).
Async methods have three possible return types: Task<TResult>, Task, and void.
The Task<TResult> return type is used for an async method that contains a return statement in which the operand has type TResult.
Async methods that don't contain a return statement or that contain a return statement that doesn't return an operand usually have a return type of Task. Such methods would be void-returning methods if they were written to run synchronously. If you use a Task return type for an async method, a calling method can use an await operator to suspend the caller's completion until the called async method has finished.
The primary use of the void return type is in event handlers, where a void return type is required. A void return also can be used to override void-returning methods or for methods that perform activities that can be categorized as "fire and forget." However, you should return a Task wherever possible, because a void-returning async method can't be awaited. Any caller of such a method must be able to continue to completion without waiting for the called async method to finish, and the caller must be independent of any values or exceptions that the async method generates.
The caller of a void-returning async method can't catch exceptions that are thrown from the method, and such unhandled exceptions are likely to cause your application to fail. If an exception occurs in an async method that returns a Task or Task<TResult>, the exception is stored in the returned task, and rethrown when the task is awaited. Therefore, make sure that any async method that can produce an exception has a return type of Task or Task<TResult> and that calls to the method are awaited.
Asynchronous methods cannot declare
The await operator can be applied to a Task inside a method marked as async. It causes the method to stop execution at that point and wait until the task completes.
Using await does not block the caller’s thread – rather control is returned to the caller. This means that the calling thread is not blocked, so for example the user interface thread would not be blocked when awaiting a task.
When the task completes, the method resumes executing at the same point in the code. This includes returning to the try scope of a try-catch-finally block (if one is present). await cannot be used in a catch or finally block.
Exceptions that occur inside an async method are stored in the task and thrown when the task is
awaited. These exceptions can be caught and handled inside a try-catch block.
Asynchronous methods that take a long time to complete should support cancellation. Typically, cancellation is invoked as follows:
CancellationTokenSourceobject is created.
CancellationTokenSource.Tokeninstance is passed to a cancellable asynchronous method.
- Cancellation is requested by calling the
The task then cancels itself and acknowledges the cancellation.
Using async and await greatly simplifies the code required to spawn long-running operations on background threads without blocking the main thread. They also make it easy to access the results when the task has completed.