How to handle a cancelled background task (XAML)
Learn how to make a background task that recognizes cancellation requests and stops work, reporting the cancellation to the app using persistent storage.
Note For Windows Phone Store apps, if the device becomes low on memory, background tasks may be terminated without any warning and without raising the OnCanceled event. This helps to ensure the user experience of the app in the foreground. Your background task should be designed to handle this scenario.
What you need to know
Technologies
Prerequisites
- This topic assumes you have already created a background task class, including the Run method that is used as the background task entry point. To get started quickly building a background task, see Quickstart: Create and register a background task. For more in-depth information on conditions and triggers, see Support your app with background tasks.
Instructions
Step 1: Use the OnCanceled method to recognize cancellation requests
Write a method to handle the cancellation event.
-
Create a method named OnCanceled that has the following footprint. This method is the entry point called by the Windows Runtime whenever a cancellation request is made against your background task.
The OnCanceled method needs to have the following footprint:
-
Add a flag variable called _CancelRequested to the background task class. This variable will be used to indicate when a cancellation request has been made.
-
In the OnCanceled method you created in step 1, set the flag variable _CancelRequested to true.
The full background task sample OnCanceled method sets _CancelRequested to true and writes potentially useful debug output:
-
In the background task's Run method, register the OnCanceled event handler method before starting work.
For example, use the following line of code:
Step 2: Handle cancellation by exiting the Run method
When a cancellation request is received, the Run method needs to stop work and exit by recognizing when _cancelRequested is set to true.
-
Modify the code of your background task class to check the flag variable while it's working. If _cancelRequested set to true, stop work from continuing.
The background task sample includes a check that stops the periodic timer callback if the background task is canceled:
if ((CancelRequested == false) && (Progress < 100)) { Progress += 10; TaskInstance->Progress = Progress; } else { PeriodicTimer->Cancel(); // TODO: Record whether the task completed or was cancelled. }
Note The code sample shown above uses the IBackgroundTaskInstance.Progress property being used to record background task progress. This lets the Windows Runtime report progress back to the app using the BackgroundTaskProgressEventArgs class. -
Modify the Run method so that after work has stopped, it records whether the task completed or was cancelled.
The background task sample records status in LocalSettings:
if ((CancelRequested == false) && (Progress < 100)) { Progress += 10; TaskInstance->Progress = Progress; } else { PeriodicTimer->Cancel(); // // Write to LocalSettings to indicate that this background task ran. // auto settings = ApplicationData::Current->LocalSettings; auto key = TaskInstance->Task->Name; settings->Values->Insert(key, (Progress < 100) ? "Canceled" : "Completed"); // // Indicate that the background task has completed. // Deferral->Complete(); }
Remarks
You can download the background task sample to see these code examples in the context of methods.
For illustrative purposes, the sample code above shows only portions of the Run method (and callback timer) from the background task sample.
Run method example
The complete Run method, and timer callback code, from the background task sample are shown below for context:
void SampleBackgroundTask::Run(IBackgroundTaskInstance^ taskInstance) { // // Associate a cancellation handler with the background task. // taskInstance->Canceled += ref new BackgroundTaskCanceledEventHandler(this, &SampleBackgroundTask::OnCanceled); // // Get the deferral object from the task instance, and take a reference to the taskInstance. // Deferral = taskInstance->GetDeferral(); TaskInstance = taskInstance; auto timerDelegate = [this](ThreadPoolTimer^ timer) { if ((CancelRequested == false) && (Progress < 100)) { Progress += 10; TaskInstance->Progress = Progress; } else { PeriodicTimer->Cancel(); // // Write to LocalSettings to indicate that this background task ran. // auto settings = ApplicationData::Current->LocalSettings; auto key = TaskInstance->Task->Name; settings->Values->Insert(key, (Progress < 100) ? "Canceled" : "Completed"); // // Indicate that the background task has completed. // Deferral->Complete(); } }; TimeSpan period; period.Duration = 500 * 10000; // 500 milliseconds PeriodicTimer = ThreadPoolTimer::CreatePeriodicTimer(ref new TimerElapsedHandler(timerDelegate), period); }
Related topics
- Quickstart: Create and register a background task
- How to register a background task
- How to debug a background task
- How to get a list of pending background tasks
- How to monitor background task progress and completion
- How to declare background tasks in the application manifest
- How to debug a background task
- Guidelines and checklists for background tasks