[This documentation is preliminary and is subject to change.]
The Windows Runtime provides a consistent set of patterns for creating and managing asynchronous operations.
The following sections describe asynchronous programming in the Windows Runtime and its representation in JavaScript, C#, Microsoft Visual Basic .NET, and Microsoft Visual C++.
Advantages of asynchronous programming
Your Metro style app remains responsive to user input when it takes advantage of the Windows Runtime asynchronous programming model. You can start a long-running task without blocking the UI thread, and you can receive the results of the task at a later time. You can cancel tasks and receive progress notifications as tasks run in the background. You don't need to manage threads explicitly or interact directly with the underlying concurrence implementation.
Many Windows Runtime features are exposed as asynchronous functions, like
MediaCapture and
StorageFile. By convention, the names of asynchronous functions
end with "Async" to indicate that part of their execution may take place after the call has returned.
When you use asynchronous APIs in your Metro style app, your code makes non-blocking calls in a consistent way. When you implement these asynchronous patterns in your API, callers can understand and use your code in a predictable way.
The Windows Runtime provides asynchronous patterns that are natural for each programming language.
These patterns enable your code to:
- Subscribe to optional progress notifications
- Subscribe to completed notifications
- Start an asynchronous operation
- Request cancellation of an asynchronous operation
- Request release of resources by using a close function
- Retrieve results from a completed asynchronous operation
Asynchronous patterns in Metro style apps with JavaScript
In JavaScript, asynchronous programming follows the
Common JS Promises/A proposed standard and works with toolkits like jQuery, Dojo, and Windows Library for JavaScript.
A promise object represents a promise for a future value that will be fulfilled eventually. You get a promise object from a factory function, which by convention has a name that ends with "Async".
Simple asynchronous functions in JavaScript
In many cases, calling an asynchronous function is almost as simple as calling a conventional function. The difference is that you
use the then function to assign the handler for the future result of the long-running operation, and to start the operation.
The following code example shows how to create a temporary file asynchronously by using the
createFileAsync function.
// Assign the URI to download from.
var uriContoso = new Windows.Foundation.Uri("http://www.contoso.com");
// Get the folder for temporary files.
var tempFolder = Windows.Storage.ApplicationData.current.temporaryFolder;
// Create the temp file asynchronously.
// The then function implicitly sets up the promise object
// and starts the asynchronous operation.
tempFolder.createFileAsync("tempfile.txt").then(function (tempFile) {
console.log("Created temp file at: " + tempFile.path);
});
This is equivalent to the following code example, which doesn't use the
then function. Instead, the promise object is used directly and the asynchronous operation is started by calling the start method explicitly.
// Assign the URI to download from.
var uriContoso = new Windows.Foundation.Uri("http://www.contoso.com");
// Get the folder for temporary files.
var tempFolder = Windows.Storage.ApplicationData.current.temporaryFolder;
// Get a promise to create the temp file.
var promise = tempFolder.createFileAsync("tempfile.txt");
// Assign the completion handler function.
promise.operation.completed = function (asyncOp) {
var path = asyncOp.operation.getResults().path;
console.log("Created temp file at: " + path );
};
// Start the asynchronous operation.
promise.operation.start();
In both cases, your code continues to run, and when the background operation completes, the completion function runs and displays the result of the operation by calling
getResults on the provided
asyncOperation. You can end the asynchronous operation while it's running by calling the
cancel function.
Chained asynchronous functions in JavaScript
You can chain asynchronous operations by calling the
then function on the promise that is returned by the previous
then function.
The following code example shows how to download a web page asynchronously to a file by using the
createFileAsync and
startDownloadAsync functions and nested
then functions.
// Assign namespace aliases for convenience.
var WS = Windows.Storage;
var WN = Windows.Networking;
// Assign the URI to download from.
var uriContoso = new Windows.Foundation.Uri("http://www.contoso.com");
// Get the folder for temporary files.
var tempFolder = WS.ApplicationData.current.temporaryFolder;
// Create the temp file asynchronously.
tempFolder.createFileAsync("tempfile.txt").
then(function (tempFile) {
// The then function gets the result from the asynchronous file-creation operation,
// which is a StorageFile, and passes it to the anonymous completion handler function.
// This file is passed to the startDownloadAsync function to be used as the
// destination file for the download.
var backgroundDownloader = new WN.BackgroundTransfer.BackgroundDownloader();
return backgroundDownloader.startDownloadAsync(uriContoso, tempFile);
}).
then(function () {
// The then function starts the async download operation.
console.log("File download complete.");
});
The
createFileAsync function returns a promise, and the
then function assigns the provided completion handler to the promise's
operation property. This function executes when the asynchronous operation completes. When the promise is set up, the
then function starts the asynchronous operation.
Asynchronous functions with progress and error handling in JavaScript
You can track the progress of an asynchronous operation by providing a notification function. You can get detailed information about error conditions by providing an error function. Use the
then function to assign the handler functions for progress notifications and error handling.
The following code example shows how to download a web page asynchronously to a file by using the
startDownloadAsync function and notifications.
// Assign namespace aliases for convenience.
var WS = Windows.Storage;
var WN = Windows.Networking;
// Assign the URI to download from.
var uriContoso = new Windows.Foundation.Uri("http://www.contoso.com");
// Get the folder for temporary files.
var tempFolder = WS.ApplicationData.current.temporaryFolder;
// Create the temp file asynchronously.
tempFolder.createFileAsync("tempfile.txt").
then(function (tempFile) {
// The createFileAsync call succeeded, so start the download operation.
var backgroundDownloader = new WN.BackgroundTransfer.BackgroundDownloader();
return backgroundDownloader.startDownloadAsync(uriContoso, tempFile);
}).
then(function () {
console.log("File download complete.");
},
// Define the error handling function.
function (error) {
alert("BackgroundDownload failed.");
},
// Define the progress handling function.
function (progress, resultSoFar) {
console.log("Bytes retrieved: " + progress.bytesReceived);
});
The
createFileAsync function returns immediately. The
then function assigns the progress and error handlers, and it starts the asynchronous operation.
When the
startDownloadAsync function has updates to report, it calls the progress handler with progress and intermediate result objects. If an error occurs during the asynchronous operation, the error handler is called instead of the completed handler.
Asynchronous patterns in Metro style apps with WinJS
The Windows Library for JavaScript is a toolkit for asynchronous programming. It's based on the
Common JS Promises/A proposed standard and works with toolkits like jQuery and Dojo.
A
Promise object represents a promise for a future value that will be fulfilled eventually. You get a
Promise object from a factory function, which by convention has a name that ends with "Async". The
Promise object enables the promise contract for asynchronous operations like data binding and
ListView data sources.
The
Promise object provides static utility functions for working with promises of many kinds, including
Promise and Windows Runtime async operations. For example, the
join function enables composing multiple asynchronous operations that all need to complete before the next step in the algorithm executes. For more information, see
Asynchronous programming in JavaScript.
Creating your own Promise
In addition to sophisticated utilities, the
Promise object enables easy implementation of your own asynchronous functions.
The following code example shows how to create a custom asynchronous function by using the
Promise object. The
poll function takes a function and an update period, in milliseconds, and returns a
Promise that calls the specified function periodically at the specified interval.
function pollAsync(f, interval) {
//
// Periodically run the function 'f' until it returns true. Once it
// returns true, stop polling and fulfill the promise successfully.
// If it throws an error, stop polling and fulfill the promise
// with an error.
//
var token;
return new WinJS.Promise(
function (c, e) {
token = setInterval(
function () {
try {
var result = f();
if (result) {
clearInterval(token);
c();
}
} catch (ex) {
clearInterval(token);
e(ex);
}
},
interval || 1000
);
},
function () {
// If canceled, clear the interval to stop polling.
clearInterval(token);
}
);
}
// The startPolling function calls the poll function with
// a function that is invoked every 1000 milliseconds.
function startPolling() {
pollAsync(function () { console.log("poll interval"); }, 1000).
then(function () {
console.log("polling canceled"); });
};
Asynchronous patterns in Metro style apps with C#
In C#, asynchronous programming is based on the
Task class and the
await operator. The
Task class represents an asynchronous operation. You get a
Task object from a factory function, which by convention has a name that ends with "Async". You provide the code that executes asynchronously by providing an
Action delegate. For more information, see
Asynchronous Programming with Async and Await (C# and Visual Basic).
Simple asynchronous methods in C#
In many cases, calling an asynchronous method is almost as simple as calling a conventional method. The difference is that you use the
await operator to manage the
Task that's returned by the asynchronous method. The
await operator suspends the execution of the current method until the task is complete. In the meantime, control returns to the caller of the current method. The
async modifier on the method declaration is required.
The following code example shows how to create a temporary file asynchronously by using the
CreateFileAsync method.
using System.Diagnostics;
using Windows.Storage;
using Windows.Networking.BackgroundTransfer;
async Task CreateTempFileAsync()
{
// Assign the URI to download from.
Uri uriContoso = new Uri("http://www.contoso.com");
// Get the folder for temporary files.
IStorageFolder tempFolder = Windows.Storage.ApplicationData.Current.TemporaryFolder;
// Create the temp file asynchronously. The asynchronous operation
// is created as a Task, and the await operator causes execution
// to transfer to the caller of the CreateTempFileAsync method,
// while the asynchronous operation runs in the background.
StorageFileRetrievalOperation op = tempFolder.CreateFileAsync("tempfile.txt");
Task<StorageFile> task = op.StartAsTask<StorageFile>();
var tempFile = await task;
// The following line is equivalent to the previous three lines.
// var tempFile = await tempFolder.CreateFileAsync("tempfile.txt");
// When the task completes, control returns to this
// method, the result of the task is assigned to tempFile,
// and the following line executes.
Debug.WriteLine("Created temp file at: " + tempFile.Path);
}
The
CreateTempFileAsync method blocks until the
Task created from the
StorageFileRetrievalOperation is completed. The
await operator causes execution to transfer to the caller while the task runs in the background, and when the task completes, execution transfers back to the
tempFile assignment in the
CreateTempFileAsync method.
When an app first calls your async method, control does not transfer back to the caller until the first
await operator is encountered. Even after the first
await operator, execution continues in your async method until an
await operator occurs on an incomplete task.
This means that you should write an async method so that it doesn't do a lot of work, or perform blocking calls, before its first
await, or between
await operators. Asynchronous methods are for operations that don’t need a lot of thread time. If you need to move intensive work or unavoidable blocking calls from your thread, you should put them on the thread pool using the
Task.Run method.
When a method has the
async modifier, the return type can be only
void,
Task, or
Task<T>. Typically, a return type of
void is used only in an async event handler, where
void is required. In other cases, you use
Task<T> if the completed task returns a value of type
T, or
Task if the completed task does not return a meaningful value. You can think of the
Task return type as meaning
Task<void>.
Asynchronous methods with progress and completion handling in C#
You can track the progress of an asynchronous operation by providing a notification delegate. You can get detailed information about the outcome of the operation by providing a completion delegate.
The following code example shows how to download a web page asynchronously to a file by using the
StartDownloadAsync function with progress and completion notifications.
using System.Diagnostics;
using Windows.Storage;
using Windows.Networking.BackgroundTransfer;
async Task DownloadWithProgressAndCompletedAsync()
{
// Assign the URI to download from.
Uri uriContoso = new Uri("http://www.contoso.com");
// Get the folder for temporary files.
IStorageFolder tempFolder = Windows.Storage.ApplicationData.Current.TemporaryFolder;
// Create the temp file asynchronously.
var tempFile = await tempFolder.CreateFileAsync("tempfile.txt");
// Get a DownloadOperation from the StartDownloadAsync method.
var backgroundDownloader = new Windows.Networking.BackgroundTransfer.BackgroundDownloader();
DownloadOperation op = backgroundDownloader.StartDownloadAsync(uriContoso, tempFile);
// Assign delegates for the Progress and Completed notifications.
op.Progress = new AsyncActionProgressHandler<BackgroundDownloadProgress>(DownloadProgressEventHandler);
op.Completed = new AsyncActionWithProgressCompletedHandler<BackgroundDownloadProgress>(DownloadCompletedHandler);
// Start the asynchronous operation.
await op.StartAsTask();
}
void DownloadProgressEventHandler(
IAsyncActionWithProgress<BackgroundDownloadProgress> action,
BackgroundDownloadProgress progress)
{
// Report progress on the asynchronous operation.
// For example, you could update a ProgressBar control.
Debug.WriteLine("Bytes retrieved: " + progress.BytesReceived);
}
void DownloadCompletedHandler(IAsyncActionWithProgress<BackgroundDownloadProgress> op)
{
// Perform actions based on the completion status.
if (op.Status == AsyncStatus.Error)
{
Debug.WriteLine("Error: " + op.ErrorCode);
}
else if (op.Status == AsyncStatus.Canceled)
{
Debug.WriteLine("Canceled");
}
else if (op.Status == AsyncStatus.Completed)
{
Debug.WriteLine("Download Completed");
}
}
The
StartDownloadAsync method returns a
DownloadOperation, which you use to manage the asynchronous task. Delegates for the Progress and Completed notifications are assigned, and the task is started by calling the
Start method.
When the asynchronous task has updates to report, it calls the progress handler with progress and intermediate result objects. The completed handler is called when the task completes, and you can check the result of the task by inspecting the
Status property.
Asynchronous methods with anonymous delegates in C#
You can track the progress and get detailed information about the outcome of an asynchronous operation by providing anonymous delegates. This approach avoids the proliferation of handler methods in your code.
The following code example shows how to download a web page asynchronously, with progress and completion notifications that are implemented as anonymous delegates.
using System.Diagnostics;
using Windows.Storage;
using Windows.Networking.BackgroundTransfer;
async Task DownloadWithAnonymousDelegatesAsync()
{
// Assign the URI to download from.
Uri uriContoso = new Uri("http://www.contoso.com");
// Get the folder for temporary files.
IStorageFolder tempFolder = Windows.Storage.ApplicationData.Current.TemporaryFolder;
// Create the temp file asynchronously.
var tempFile = await tempFolder.CreateFileAsync("tempfile.txt");
// Get a DownloadOperation from the StartDownloadAsync method.
var backgroundDownloader = new Windows.Networking.BackgroundTransfer.BackgroundDownloader();
DownloadOperation op = backgroundDownloader.StartDownloadAsync(uriContoso, tempFile);
// Assign delegates for the Progress and Completed notifications.
op.Progress = delegate(
IAsyncActionWithProgress<BackgroundDownloadProgress> action,
BackgroundDownloadProgress progress)
{
// Report progress on the asynchronous operation.
// For example, you could update a ProgressBar control.
Debug.WriteLine("Bytes retrieved: " + progress.BytesReceived);
};
op.Completed = delegate(IAsyncActionWithProgress<BackgroundDownloadProgress> completedOp)
{
// Perform actions based on the completion status.
if (completedOp.Status == AsyncStatus.Error)
{
Debug.WriteLine("Error: " + op.ErrorCode);
}
else if (completedOp.Status == AsyncStatus.Canceled)
{
Debug.WriteLine("Canceled");
}
else if (completedOp.Status == AsyncStatus.Completed)
{
Debug.WriteLine("Download Completed");
}
};
// Start the asynchronous operation.
await op.StartAsTask();
}
Uploader Comments ( learningsqlserver )