Nick's .NET Travels

Continually looking for the yellow brick road so I can catch me a wizard....

Communication and Synchronization using Background Tasks with Windows and Windows Phone 8.1

In an earlier post I covered creating a background task for Windows platform applications that would allow for synchronization in the background, triggered by change in Internet availability. However, one thing I didn’t cover is what happens when the application is in use, in this case, not only might the user be interacting with the data (loading and writing new records), they might have even forced a synchronization within the application. For this reason it may be necessary to prevent background synchronization whilst the foreground application is being used.

If you haven’t worked with Windows/Windows Phone 8.1 before the OnActivated method might be confusing in the Application class – it’s not the same as the Activated/Deactivated pair from Windows Phone 7x/8.0 where they occurred reliably when the application went into the background. For Windows/Phone 8.1 you need to look at the Window VisibilityChanged event to detect when the Window goes into the background (note that there is an issue with this on Windows 10 where it isn’t triggered when you switch to another application as all applications are windowed by default).

protected override void OnWindowCreated(WindowCreatedEventArgs args)
{
    args.Window.VisibilityChanged += WindowVisibilityChanged;
}

In the event handler I’m going to take ownership of a named Mutex when the Window is visible, and release it when the Window is no longer visible:

private static Mutex backgroundMutex = new Mutex(false,"BackgroundSync");
private async void WindowVisibilityChanged(object sender, Windows.UI.Core.VisibilityChangedEventArgs e)
{
    if (e.Visible)
    {
        backgroundMutex.WaitOne();

        await ReregisterTasks();
    }
    else
    {
        backgroundMutex.ReleaseMutex();
    }
}

You’ll notice that after taking ownership of the Mutex I then reregister my background task:

private async Task ReregisterTasks()
{
    try
    {
        BackgroundTaskManager.UnregisterBackgroundTasks("Background Sync Task", true);
        BackgroundTaskRegistration taskReg =
            await BackgroundTaskManager.RegisterBackgroundTask(typeof(SyncTask).FullName,
                "Background Sync Task",
                new SystemTrigger(SystemTriggerType.InternetAvailable, false),
                null);
    }
    catch (Exception ex)
    {
        // Swallow this to ensure app doesn't crash in the case of back ground tasks not registering
        Debug.WriteLine(ex.Message);
    }
}

The reason for this is that we want to cancel any running background task (the “true” parameter passed into the UnregisterBackgroundTasks call).

In the background task I have a Mutex with the same name (Named Mutexes are shared across processes so a great way to communicate between foreground/background tasks). At the beginning of the Run method I attempt to acquire the Mutex: if this succeeds I know my foreground application isn’t visible; if this fails (which it will do immediately since I specified a wait time of 0) it will simply return from the task as we don’t want to sync whilst the foreground application is visible. If the background task is going to run, I immediately release the Mutex which will ensure that if the foreground application is made visible, or launched, it won’t be blocked waiting to acquire the Mutex.

private static Mutex foregroundMutex = new Mutex(false,"BackgroundSync");
public async void Run(IBackgroundTaskInstance taskInstance)
{
    try
    {
        if (!foregroundMutex.WaitOne(0)) return;
        foregroundMutex.ReleaseMutex();
        // do the rest of background task

It’s important within your background task to override and handle the OnCanceled method so that if the background task is executing when it is unregistered, the task can be cancelled gracefully.

Pingbacks and trackbacks (1)+

Comments are closed