From a background task, it's perfectly allowable to issue a tile update, for instance, when procedding a raw push notification in that task and updating a tile in response. With secondary tiles, you might also want to update the tile's arguments so that it launches into different content relevant to the tile update. However, secondary tile arguments are statically defined when the tile is pinned and cannot be changed later.

To work around this, you can use a set of static identifiers that you then dynamically map to your variable data. It's simplest to just keep a table of secondary tile IDs mapped to their dynamic arguments, in which case you're probably not using the static arguments at all.

Another question with background tasks is whether it's possible to do file I/O therein, because clearly if you're modifying a table of secondary tile arguments in a file you'll be doing file I/O. The thing to remember here is that if you use any kind of async APIs in the process, you need to make sure the background task stays active until the async work is complete. To do this, you use the deferral mechanism.

In C#, the general pattern is like this:

public async void Run(IBackgroundTaskInstance taskInstance)
{
    var deferral = taskInstance.GetDeferral();
    var contents = await DoAsyncWork();
    deferral.Complete();
}

In JavaScript, the deferral is found on the WebUIBackgroundTaskRuntimeClass object. You retrieve this in the worker with Windows.UI.WebUI.WebUIBackgroundTaskInstance.current, then call its getDeferral method, do your async work, and then call the deferral's completed method when you're done.

var task = Windows.UI.WebUI.WebUIBackgroundTaskInstance.current;
ver deferral = task.getDeferral();

DoWorkAsync().done(function () {
    deferral.completed();
    close();  //Shut down the background task
});

Note that JavaScript it's also necessary to call close() when the task is finished (which is WorkerGlobalScope.close()).

 


Background tasks, depending on the conditions which trigger them, can run when their associated app is also running. The question then arises: how can the background task communicate with the app?

As noted in yesterday’s post, a background task can write to the app’s appdata areas, which is the way for the background task to pass information to the app. The app, for that matter, can also store information there for a background task to find when it’s next run.

When the background task writes data, the question then becomes how the background task can tell the app that there’s new data available.

There are two ways to do this. First is the completed event that’s part of the BackgroundTaskRegistration class. The app gets an instance of this class back from BackgroundTaskBuilder.register when it sets up a background task, after which it can then assign a handler for completed. This works well, then, for a background task that does some work that the app wants to pick up when the task is completely finished. Because the app knows which background task was associated with that particular handler, it knows where to look for the appropriate appdata.

The Background task sample in the Windows SDK uses completed handlers all over the place to give visual output when a task is complete (and also as it supports progress). In the JavaScript version of the sample, the handler is found at the end of the js/global.js file. The attachProgressAndCompletedHandlers function earlier in that file is where the handlers are assigned, and this function is called from the earlier registerBackgroundTask that call the WinRT APIs.

The second means of communication works at any time during execution of the background task, which is calling Windows.Storage.ApplicationData.signalDataChanged. This will raise a Windows.Storage.ApplicationData.datachanged event in the app (assuming it’s listening), as is also raised when Windows roams new app data from the cloud. The trick here is that the event doesn’t receive any indication of what data, exactly, was changed, so it needs to go examine any data that it expects might have changed.

Clearly, though, if an app only has one or a small number of background tasks that write to local appdata, then there’s not much to go inspect (it’s less likely that a background task would write to roaming appdata, though that’s not out of the question). So it’s workable–it just takes a little more work!

To see this in action, take the aforementioned sample, and navigate to the Tasks project (a C# project) and open SampleBackgroundTask.cs. Within PeriodicTimerCallback, add the following after the line that starts with settings.Values[key] == …:

Windows.Storage.ApplicationData.Current.SignalDataChanged();

The in the main project of the sample (again using the JavaScript variant), open js/sample-background-task-with-condition.js and add the following at the end of the ready method near the top (after the line that reads SampleBackgroundTaskWithCondition.updateUI();)

Windows.Storage.ApplicationData.current.ondatachanged = function (appdata) {
    console.log(“Appdata changed.”);
}

Set a breakpoint on console.log, then run the app and go to scenario 3. Click the Register button which will execute the ondatachanged assignment above. Then pull down the Suspend menu where you can trigger the SampleBackgroundTaskWithCondition:

background task selection

After the task does it’s work (you’ll see progress reported), it will call SignalDataChanged which should hit your breakpoint.

 


Background tasks, though they are essentially extensions of a app, only have limited capabilities where using the WinRT APIs are concerned. They can access the app’s appdata folders and settings, for example, and perform file I/O with Windows.Storage APIs. No problem there. Background tasks cannot, however, generate UI with the exception of issuing toast notifications and tile update.

Background tasks are also able to perform string lookups in resource files using the Windows.ApplicationModel.Resources.ResourceLoader class or Windows.ApplicationModel.Resources.Core.ResourceManager.current, meaning that they do have access to the app’s localized content.

One issue that comes up with background tasks written in JavaScript is that the task itself, which runs as a web worker, cannot employ the WinJS library. As a result, a JavaScript background task cannot access resources through WinJS.Resources.getString, and occasionally this leads developers to think that background tasks cannot access resources at all. But because this particular WinJS API is implemented with the WinRT APIs, you can just use the latter directly.