Asynchronous programming

In this topic

Synchronous code execution
proceeds in a linear path to process a queue of instructions in order. In this mode of execution, a particular set of code in the queue cannot be executed until all instructions ahead of it have been completed. This works fine for code that completes quickly, but it can create a bottleneck if working with processes that take longer to execute. Such bottlenecks cause frustration for users of your app, as they make the UI unresponsive until the blocking code completes.

By contrast, code executed asynchronously does not proceed in a linear fashion. Instead, code is executed on an available thread in the thread pool and results (if any) are returned upon completion. This allows you to off-load execution of longer-running processes, freeing up the UI thread so the app remains responsive to user interaction.

The .NET Framework 4.5 provides a simplified asynchronous approach that allows you to write your code in the familiar logical and linear structure that you use for synchronous code. The .NET APIs use asynchronous execution in areas where performance may be an issue, such as web access, working with files, and media capture.

ArcGIS Runtime SDK for .NET also leverages the .NET Framework 4.5 asynchronous pattern to provide asynchronous methods throughout the API. Although calling an asynchronous method requires slightly different syntax than a synchronous call, the new pattern hides much of the complexity involved and allows your code to be written with a much more linear structure compared to previous asynchronous approaches.

Task-based asynchronous pattern

In the .NET task-based asynchronous pattern (TAP), asynchronous functions are represented by System.Threading.Tasks.Task and System.Threading.Tasks.Task<TResult> types. Task<TResult> represents operations that return a value of type TResult and Task is for functions that don't return a value. The async keyword is used to mark a function as asynchronous, which must return one of those two types.

The following example shows the signature for an asynchronous function. It is marked with the async keyword and has a return type of Task<string>. By convention, asynchronous functions are named with the suffix Async.

private async Task<string> GetSiteContentAsync()
{
}

As mentioned previously, calls made to an asynchronous function will return Task or Task<TResult> objects, which represent ongoing work. The task contains information about the state of the asynchronous process and, when it completes, either the final result from the process or the exception thrown when the process failed.

To get the actual value returned from the asynchronous operation, you need to await completion of the task using the await keyword. When execution hits a line with await, control is returned to the calling function until the task completes.

The following example shows a call to an asynchronous method (System.Net.Http.HttpClient.GetStringAsync) to get a Task<string>. It then uses await to get the string result of the task operation.

private async Task<string> GetSiteContentAsync()
{
// use an HttpClient to get the contents of a web page
var client = new System.Net.Http.HttpClient();
// call the async method GetStringAsync to return a Task<string>
// the task will asynchronously read the contents of the specified web site
Task<string> getContentsTask = client.GetStringAsync("http://www.esri.com");
// await the task to get the result
// note: control is returned to the calling code at this point (until the task completes)
string urlContents = await getContentsTask;
// code following "await" does not execute until the task completes
return urlContents;
}

Note:

Functions that use the await keyword must be marked with the async keyword in their definition.

Although it should be avoided if possible, an async function can be defined with a void return type. A common scenario is when defining an async event handler, whose signature must retain the void return type.

Caution:

An async function with a void return type cannot be awaited, and the caller won't be able to catch any exceptions thrown by the function.

Async methods in ArcGIS Runtime

ArcGIS Runtime SDK for .NET leverages the task-based asynchronous pattern used by the .NET Framework. Throughout the API, you'll find several asynchronous methods, all of which are named using the Async suffix. Many of the ArcGIS Runtime methods wrap calls to REST services, and since they require web communication, it makes sense to make such calls asynchronously. This ensures that your app stays responsive while a response from the server is awaited.

Sometimes, it's not the result of an asynchronous method that's important, but waiting for a particular task to complete. For example, you may have code that depends on the loading of all layers in the map. You can await the MapView.LayersLoadedAsync method to ensure loading of all layers is complete, as shown in the following example.

Asynchronous tasks generally run on a background thread for your application, which may have ramifications for working with objects in the UI. See Threading considerations for more information.

Handle exceptions from asynchronous calls

If an error is encountered while executing an asynchronous call, System.Threading.Tasks.Task.Exception will be set. You can trap for such exceptions by wrapping the await call in a try catch block such as the one shown in the following code example. If the exception is raised from the underlying REST call, you can expect an Esri.ArcGISRuntime.Http.ArcGISWebException to be thrown.

Cancel execution

A task can be canceled during the course of its asynchronous execution by using a System.Threading.CancellationToken, which can optionally be passed into most ExecuteAsync methods for a task. A task can be canceled manually (for example, if the user clicks a Cancel button) or by specifying a maximum time interval that the task is allowed to run. The following code example incorporates both techniques by setting a time limit (10 seconds) after which the task will be canceled and also calls the Cancel method if the user clicks the Cancel button.