6
votes

I am following https://docs.microsoft.com/en-us/windows/uwp/launch-resume/create-and-register-a-background-task document to create a background task which will run every 15 minutes and ping a service.

  1. Created a Windows Runtime Component project with a public sealed class implementing IBackgroundTask

    namespace PeriodicBackgroundTask
    {
        public sealed class FifteenMinutePeriodicTimer : IBackgroundTask
        {
            private static readonly FileLogWriter mWriteLogToFile = new FileLogWriter();
            public FifteenMinutePeriodicTimer() { }
    
            public void Run(IBackgroundTaskInstance taskInstance)
            {
                try
                {
                    taskInstance.Canceled += new BackgroundTaskCanceledEventHandler(OnCanceled);
                    mDeferral = taskInstance.GetDeferral();
                    mWriteLogToFile.log("Starting periodic timer at " + DateTime.Now.ToString());
    
                    // Calling method to do a Post call to a service.
    
                    mWriteLogToFile.log("Finishing periodic timer at " + DateTime.Now.ToString());
                }
                catch (Exception ex)
                {
                    mWriteLogToFile.log("Fifteen Minute periodic timer failed.", ex);
                }
                finally
                {
                    // Adding some buffer for async processes to finish.    
                    Task.Delay(TimeSpan.FromSeconds(15)).Wait();
                    mDeferral.Complete();
                }
            }
    
            private void OnCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
            {
                mWriteLogToFile.log("Fifteen minute periodic timer is canceled. {0}", reason.ToString());
            }
        }
    }
    
  2. Entry in UWP application's Package.appmanifest file

    <Extension Category="windows.backgroundTasks" EntryPoint="PeriodicBackgroundTask.FifteenMinutePeriodicTimer">
      <BackgroundTasks>
        <Task Type="systemEvent" />
        <Task Type="timer" />
      </BackgroundTasks>
    </Extension>
    
  3. Registering Timer at the beginning of OnLaunched Method in App.xaml.cs

    public async static Task RegisterBackgroundTask()
    {
        foreach (var task in BackgroundTaskRegistration.AllTasks)
        {
            if (String.Equals(task.Value.Name, TASK_NAME))
            {
                mWriteLogToFile.log("Old version of fifteen minute periodic timer found. Unregistering it.");
                BackgroundExecutionManager.RemoveAccess();
                // Unregistering so that any update in Background task can be applied.
                task.Value.Unregister(true);
                break;
            }
        }
        BackgroundAccessStatus backgroundAccessStatus = await BackgroundExecutionManager.RequestAccessAsync();
        if (backgroundAccessStatus == BackgroundAccessStatus.DeniedByUser ||
        backgroundAccessStatus == BackgroundAccessStatus.DeniedBySystemPolicy)
        {
            mWriteLogToFile.log("Fifteen minute periodic timer registration failed, due to Request access status.");
            return;
        }
    
        BackgroundTaskBuilder builder = new BackgroundTaskBuilder();
        builder.Name = TASK_NAME;
        builder.TaskEntryPoint = "PeriodicBackgroundTask.FifteenMinutePeriodicTimer";
        builder.SetTrigger(new TimeTrigger(15, false));
        builder.CancelOnConditionLoss = false;
    
        var backgroundTask = builder.Register();
        if (backgroundTask != null)
        {
            mWriteLogToFile.log("Fifteen minute periodic timer registration SUCCESSFUL.");
        }
        else
        {
            mWriteLogToFile.log("Fifteen minute periodic timer registration FAILED.");
        }
    }
    

After installing the app FifteenMinuteBackgroundTimer runs 5 or 6 times. Sometimes 5, sometimes 6. When I try to debug the task using Visual Studio I am able to debug it. I am not sure, why FifteenMinuteBackgroundTimer is dying after 5 runs. Can anybody please tell me how can I debug this issue?

More Info:

Windows Build: 1607
Microsoft.NETCore.UniversalWindowsPlatform: 5.1.0

2

2 Answers

1
votes

It is very likely you are running into two policies related to power.

  1. Periodic timer triggers are considered opportunistic. Depending on how much energy is being used in the background (while not powered and screen off), your task might not get fired in order to conserve energy for other critical user activities (like receiving an SMS, push or incoming phone call). To verify if this is the condition you are running into: you can toggle your application to "always allowed" in the "settings->system->battery->battery by application" panel.
  2. You also mentioned that networking is non functional when your trigger runs if the screen is off. In standby systems, you need to specify IsNetworkRequested as part of the trigger registration so the system takes the network interface into full operational mode for the duration of your task. Refer to the documentation here: https://docs.microsoft.com/en-us/uwp/api/Windows.ApplicationModel.Background.BackgroundTaskBuilder
4
votes

Can anybody please tell me how can I debug this issue?

After you register the background task, you will find the background task show in the drop down list of Lifecycle Events toolbar. Set a break point on the background task then click the background name in the toolbar the visual studio will trigger the background task and you can debug. More details please reference Debug a background task.

enter image description here

why FifteenMinuteBackgroundTimer is dying after 5 runs.

If you run any asynchronous code in your background task, then your background task needs to use a deferral.It seems like you create the deferral instance but didn't get a deferral from the IBackgroundTaskInstance. So you may need to get the deferral firstly.

public void Run(IBackgroundTaskInstance taskInstance)
{
    mDeferral = taskInstance.GetDeferral();
    ...
    mDeferral.Complete();       
}

And you may not need Task.Delay(TimeSpan.FromSeconds(15)).Wait(); for adding some buffer for async processes to finish since deferral can help you do this. The background task can only run 30s in total, actually the running time may only be 25s, if you set a delay in the background task may lead it cannot complete the task and force closed.