from:http://blogs.msdn.com/b/windowsappdev/archive/2012/05/24/being-productive-in-the-background-background-tasks.aspx
In my previous post (Being productive in the background), I explained the Windows 8 background model and how your app can be productive even when it’s not on screen in a power efficient manner. In today’s post, I will talk about background tasks and how your app can run code in the background even when it is suspended. I will describe two common scenarios with example code that show you how to run your own app code in the background; downloading POP email every 15 minutes with a lock screen capable app and how any app can do work in the background when the device is on AC power.
Background task triggers are designed for varied scenarios and applications, and so have different requirements and resource management constraints. Some background task triggers are designed for apps that always need to stay up to date (e.g. email, VOIP) while others are designed for more opportunistic scenarios (e.g. running a maintenance task on AC or when certain system conditions change). The apps that always need to stay up to date need to be on the lock screen, this is limited to 7 apps; more on this later in the post. In contrast, if you want to do opportunistic work, any app can use the maintenance trigger which runs on AC or certain system triggers. To use these triggers the app doesn’t need to be on the lock screen. Apps on the lock screen have more relaxed resource management constraints because they need to run more frequently (that’s why we limit the number and put the user in control!). I will talk about these details later.
You don’t have to use background tasks if you simply want to keep your app fresh with content. You can always use live tiles or scheduled notifications as we explained in the post Create a great tile experience. With this introduction, let’s dive into the code!
As we’ve seen in my previous post, sometimes your app needs its own code to provide functionality in the background. For example, let’s say you want to add all the photos in the Pictures Library to your app database or process them in some way (e.g. generate thumbnails). You can do this when your app is running in the foreground and interacting with the user, or you can use background tasks with a maintenance trigger which runs in the background only when the device is on AC power. The maintenance trigger is available to everyone and your app doesn’t need to be on the lock screen. The advantage of using a maintenance trigger background task is that it is guaranteed to not interfere with the user’s activity and, runs only on AC power. So you don’t need to worry about excessive battery usage.
This code example shows the maintenance background task calls ProcessPictures class to process the files when the task runs. The task runs every 8 hours to look for new files to process. The background task also registers for a cancel handler because maintenance background tasks are cancelled when the device transitions to battery power. In the cancel handler, the processing of files is cancelled. If you don’t return from the cancel handler within 5 seconds, Windows will terminate the app. Note these code examples assume knowledge of the background task and the trigger classes. For more info about these classes, see theWindows.ApplicationModel.Background namespace documentation on Dev Center.
public sealed class MaintenanceBackgroundTask: IBackgroundTask { private ProcessPictures processPic; public MaintenanceBackgroundTask() { // Code to process the pictures processPic = new ProcessPictures(); } //Main Run method which is activated every 8 hours async void IBackgroundTask.Run(IBackgroundTaskInstance taskInstance) { taskInstance.Canceled += taskInstance_Canceled; // Because these methods are async, you must use a deferral // to wait for all of them to complete BackgroundTaskDeferral deferral = taskInstance.GetDeferral(); List<StorageFile> list = new List<StorageFile>(); int count = await processPic.EnumerateFiles(list); bool retval = await processPic.ProcessFiles(list); deferral.Complete(); } // Cancel handler, called whenever the task is canceled void taskInstance_Canceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason) { // Device is now on DC power, cancel processing of files processPic.Cancel = true; } }
// This JS lives within maintenanceBackgroundTask.js var processPic = new processPictures(); var count = 0; var retval = false; function onCanceled(cancelSender, cancelReason) { // Device is now on DC power, cancel processing of files processPic.cancel = true; } backgroundTaskInstance.addEventListener("canceled", onCanceled); var list = []; processPic.enumerateFiles(list).then(function (value) { count = value; processPic.processFiles(list).then(function (value) { retval = value; // Call close() to indicate the task is complete when // all async methods have completed close(); }); });
This code example shows how to register the maintenance background task from the main app. This background task launches every 8 hours to process any pictures in the Pictures Documents Library. If you don’t need to do this work anymore, you can unregister the background task using the Unregister method of the IBackgroundTaskRegistration class.
//Registering the maintenance trigger background task private bool RegisterMaintenanceBackgroundTask() { BackgroundTaskBuilder builder = new BackgroundTaskBuilder(); builder.Name = "Maintenance background task"; builder.TaskEntryPoint = "MaintenanceTask.MaintenaceBackgroundTask"; // Run every 8 hours if the device is on AC power IBackgroundTrigger trigger = new MaintenanceTrigger(480, false); builder.SetTrigger(trigger); IBackgroundTaskRegistration task = builder.Register(); return true; }
function registerMaintenanceBackgroundTask() { var builder = new Windows.ApplicationModel.Background.BackgroundTaskBuilder(); builder.name = "Maintenance background task"; builder.taskEntryPoint = "js\\maintenanceBackgroundTask.js"; //Run every 8 hours if the device is on AC power var trigger = new Windows.ApplicationModel.Background.MaintenanceTrigger(480, false); builder.setTrigger(trigger); var task = builder.register(); return true; }
You must declare Background tasks in your app manifest. Start by opening your app’s manifest in Visual Studio and from the Declarations tab add the Background Tasks declarations from the drop down menu. Choose the appropriate task type and specify your Entry point (class name of the background task) or Start page if you are using a JavaScript background task.
Figure 1 - Background task manifest declarations
You can view the contents of the manifest by right clicking it and selecting View Code. Be aware that the maintenance task can run only in the system-provided host (backgroundTaskHost.exe or wwahost.exe for JavaScript) and therefore you can’t specify any Executable attribute. The task type of Maintenance trigger is systemEvent as you can see in the manifest snippet here.
<Extension Category="windows.backgroundTasks" EntryPoint="MaintenanceTask.MaintenaceBackgroundTask"> <BackgroundTasks> <Task Type="systemEvent" /> </BackgroundTasks> </Extension>
In JavaScript EntryPoint is replaced by a StartPage attribute.
<Extension Category="windows.backgroundTasks" StartPage="js\maintenaceBackgroundTask.js">
For more info on using background tasks, see the whitepaper Introduction to background tasks and the Dev Center for API usage.
In this example, we need the app to run predictably and frequently in the background. You can get this by placing your app on the lock screen.
Because an app uses background tasks to always stay up-to-date even when the user isn’t using their Windows 8 device, the way a user controls what apps can use these background tasks is by granting them permission to appear on the lock screen. This is a natural fit because the lock screen is designed to provide users info about their apps without the need for them to unlock their Windows 8 device. This relationship is a two-way street: your app can use these types of background tasks only if it is on the lock screen and, likewise, your app can appear on the lock screen only if it requests to use these types of background tasks.
Figure 2 - Lock screen personalization UI and lock screen capable apps
Because a relatively small number of apps can be placed on the lock screen, it is important for your app to provide a good lock screen experience. If it doesn’t, users will likely remove it to make room for something else. Examples of apps that fit this mold are communication apps; e.g. a mail app that shows a count of unread email messages, a calendar app that shows upcoming appointments in the detailed status slot, or a messaging app that shows how many messages a user has missed. More information about the lock screen, including more details on what makes an app a good candidate for appearing on it, is available on Dev Center.
This example code shows how to register a time trigger background task that runs every 15 minutes if the Internet is available using theBackgroundTaskBuilder class. If the Internet is not available then your background task doesn’t run. Instead, it waits for the Internet to be available and then automatically runs. This is another useful feature of background tasks that prevents unnecessary work from happening and preserving device battery life. Without the condition, app code would have to run and then detect that there is no network connectivity and then error out because it couldn’t download the mail. The mail will be downloaded regardless of whether the app is in the foreground or not. It will also download if the device is in Connected Standby.
private bool RegisterTimeTriggerBackgroundTask() { BackgroundTaskBuilder builder = new BackgroundTaskBuilder(); builder.Name = "Pop mail background task"; builder.TaskEntryPoint = "MailClient.PopMailBackgroundTask"; // Run every 15 minutes if the device has internet connectivity IBackgroundTrigger trigger = new TimeTrigger(15, false); builder.SetTrigger(trigger); IBackgroundCondition condition = new SystemCondition(SystemConditionType.InternetAvailable); builder.AddCondition(condition); IBackgroundTaskRegistration task = builder.Register(); return true; }
function registerTimeTriggerBackgroundTask() { var builder = new Windows.ApplicationModel.Background.BackgroundTaskBuilder(); builder.name = "Pop mail background task"; builder.taskEntryPoint = "js\\popMailBackgroundTask.js"; //Run every 15 minutes if the device has internet connectivity var trigger = new Windows.ApplicationModel.Background.TimeTrigger(15, false); builder.setTrigger(trigger); var condition = new Windows.ApplicationModel.Background.SystemCondition( Windows.ApplicationModel.Background.SystemConditionType.internetAvailable); builder.addCondition(condition); var task = builder.register(); return true; }
The time trigger is available only to apps on the lock screen, as described previously. To programmatically request placement on the lock screen, you have to use the BackgroundExecutionManager class. If the user doesn’t put your app on the lock screen then your background tasks won’t run. If so, you may have to fall back to using a background task which doesn’t require lock screen or perform the work when the user uses your app. So that users don’t get asked over and over, the system prompts the user once. If they say no and want to add it later, they can do so manually.
public async Task<bool> ObtainLockScreenAccess() { BackgroundAccessStatus status = await BackgroundExecutionManager.RequestAccessAsync(); if (status == BackgroundAccessStatus.Denied || status == BackgroundAccessStatus.Unspecified) { return false; } return true; }
function obtainLockScreenAccess() { Windows.ApplicationModel.Background.BackgroundExecutionManager.requestAccessAsync().then(function (status) { if (status === Windows.ApplicationModel.Background.BackgroundAccessStatus.denied || status === Windows.ApplicationModel.Background.BackgroundAccessStatus.unspecified){ return false; } return true; }); }
This code example shows the main background task that downloads email every 15 minutes. It doesn’t go into detail describing how to update the tile and badges of your app as that was previously covered in the blog post Creating a great tile experience.
void IBackgroundTask.Run(IBackgroundTaskInstance taskInstance) { int count = popmailClient.GetNewMails(); // Update badge on lock screen with the mail count popmailClient.UpdateLockScreenBadgeWithNewMailCount(count); IList<string> mailheaders = popmailClient.GetNewMailHeaders(); // Update app tile with the subjects of the email popmailClient.UpdateTileWithSubjects(mailheaders); }
//This JS lives within popMailBackgroundTask.js var count = popmailClient.getNewMails(); // Update badge on lock screen with the mail count popmailClient.updateLockScreenBadgeWithNewmailCount(count); var mailheaders = popmailClient.getnewMailHeaders(); // Update app tile with the subjects of the email popmailClient.updatetileWithSubjects(mailheaders); close();
To add your app to the lock screen , it needs to specify the lock screen notifications type available in the Application UI tab of the manifest.
Figure 3 - Background task manifest declarations
This is a code snippet of the manifest (generated by the wizard) of an app that needs to be on the lock screen and displays badges and toasts on the lock screen. The time trigger task can run only in the system provided host (backgroundTaskHost.exe or wwahost.exe for JavaScript) and therefore you can’t specify any Executable attribute. The task type is timer as you can see from the manifest.
<LockScreen Notification="badgeAndTileText" BadgeLogo="Images\badgelogo.png" /> <DefaultTile ShowName="allLogos" WideLogo="Images\tile-sdk.png" ShortName="LockScreen CS" /> <SplashScreen Image="Images\splash-sdk.png" BackgroundColor="#FFFFFF" /> </VisualElements> <Extensions> <Extension Category="windows.backgroundTasks" EntryPoint="MailClient.PopMailBackgroundTask"> <BackgroundTasks> <Task Type="timer" /> </BackgroundTasks> </Extension>
In JavaScript EntryPoint is replaced by a StartPage attribute.
<Extension Category="windows.backgroundTasks" StartPage="js\popMailBackgroundTask.js"
You can build more advanced VOIP, instant messaging or push email apps using other background task triggers such as Control Channel or Push Notification. Their usage is beyond the scope of this post and more info about them is provided in the Background networkingwhitepaper.
As already mentioned, background tasks were designed with power efficiency in mind and hence have CPU and network resource usage constraints applied to them. This prevents an app in the background from depleting the device’s battery without the user being aware. If an app is active and the user is interacting with it in the foreground, then no CPU or network resource constraints are applied to the app’s background tasks.
Each app on the lock screen receives 2 seconds of CPU time every 15 minutes, which can be used by all of the background tasks of the app. At the end of 15 minutes, each app on the lock screen receives another 2 seconds of CPU time for use by its background tasks. Any unused CPU time in the 15-minute interval is lost and the app can’t accumulate it. Each app not on the lock screen receives 1 second of CPU time every 2 hours. If the app uses all of its available CPU time, its background tasks are suspended until the app’s CPU quota is replenished at the next generation for CPU quota updates.
CPU usage time refers to the actual amount of CPU used by the app and not the wall clock time of the background task. For example, if the background task is waiting in its code for the remote server to respond, and it is not actually using CPU, and this wait time is not counted against the CPU quota.
CPU resource quota |
Refresh period |
|
Lock screen capable app |
2 CPU seconds |
15 minutes |
Non-lock screen capable app |
1 CPU second |
2 hours |
Network usage can represent a significant drain on a device battery, and so it is also constrained during background task execution. But if a device is running on AC power then background tasks are not network-constrained. CPU usage for a background task is always resource constrained even if the device is running on AC power.
This table characterizes network data throughput, for a resource constrained WiFi network, assuming minimal interference.
Average throughput of the network interface |
Data throughput, in megabytes (MB) |
Data throughput, in MB, for non-lock screen capable apps |
|
Every 15 minutes |
Per day |
Per day |
|
10 Mbps |
1.875 |
180 |
30 |
Even with the assigned quota for each app, sometimes these fixed resource constraints may not be enough. For those situations, there is a shared global pool from which applications can request CPU and network resources.
Details about background tasks, the global pool, its resource management constraints, and best practices are available in theIntroduction to background tasks whitepaper. It also includes a sample project with source.
So the answer to the question, “can my app perform work when it is not on screen”, is a resounding yes. The background model in Windows 8 allows your app to accomplish key end-user scenarios, like file downloads, playing audio, updating e-mail in the background or performing maintenance tasks when the device is on AC power. And because the platform closely monitors these activities, your background work will have minimal impact on the foreground app’s responsiveness or the battery life of your device.
For more detailed technical info on the background model in Windows 8 go to the Dev Center and check out the various whitepapers. If you have any questions feel free to post them here in the comments and we’ll try to respond as best we can.
-- Hari Pulapaka, Program Manager, Windows.
Thanks to Jake Sabulsky, Johnny Bregar, Kyle Beck and Suhail Khalid for their contributions and many others for their valuable feedback including Alexander Corradini, Arun Kishan, Ben Srour, Ian LeGrow, Jamie Schwartz, and John Sheehan.
Link |
Type |
Highlights |
Introduction to background tasks |
Whitepaper |
Introduces background tasks |
Background Model API namespace |
Docs |
Background model API namespace |
Background tasks sample project |
Sample project |
Demonstrates usage of background tasks |
Lock screen overview |
Conceptual documentation |
Explains the lock screen and its best practices |
Background networking |
Whitepaper |
Shows how to develop advanced apps like VOIP, instant messaging using background tasks. |
Creating a great tile experience |
Blog post |
Shows how to create a great tile experience |