Posted on 03-16-13 10:36 am
Per the MSDN documentation, PeriodicTasks run once every 30 minutes on Windows Phone devices. They are designed to fill the gap with multitasking, and allow your application to do some quick, low resource background processing on a regular basis. Uses for this include updating tiles, checking in with the backend, updating location-aware data, etc.
The idea is for the tasks to be quick and cause no disruption to the user or his/her battery life. Unfortunately, the schedule is hard-coded at 30 minutes, with no way of configuring this.
Here are two workarounds I've used in some WPH projects.
Running a task at intervals longer than 30 minutes
This is quick and simple, and completely supported. What we do here is obvious: since the task runs every 30 minutes, check if the duration between runs is long enough, and if not, skip the test until the next cycle.
DateTime lastrun;
IsolatedStorageSettings.ApplicationSettings.TryGetValue<DateTime>("lastrun", out lastrun);
if (DateTime.Now.Subtract(lastrun).TotalMinutes < 60) // 60 minutes, so run every hour
{
System.Diagnostics.Debug.WriteLine("Too soon, stopping.");
NotifyComplete();
return;
}
//add proper code for removing old value, etc.
IsolatedStorageSettings.ApplicationSettings.Add("lastrun", DateTime.Now);
This allows you to increase the duration in increments of 30 minutes, e.g. run a task every hour, hour and a half, six hours, etc.
It does not allow you to run a task every 45 minutes, for example, or anything less than 30 minutes. For that, we'll use option 2.
Running a task at intervals shorter than 30 minutes [Homebrew only]
This method is a little dirty. Here's the code, followed by some discussion.
DateTime lastrun;
IsolatedStorageSettings.ApplicationSettings.TryGetValue<DateTime>("lastrun", out lastrun);
if (DateTime.Now.Subtract(lastrun).TotalMinutes < 60) // 60 minutes, so run every hour
{
System.Diagnostics.Debug.WriteLine("Too soon, stopping.");
NotifyComplete();
return;
}
//add proper code for removing old value, etc.
IsolatedStorageSettings.ApplicationSettings.Add("lastrun", DateTime.Now);
// Launch the task in 6 minutes
ScheduledActionService.LaunchForTest("task", TimeSpan.FromMinutes(6));
What this does is break the rules and call LaunchForTest from within the task, allowing it to re-execute itself at a desired time. Per the MSDN documentation,
Use this method during application development to test your background agent implementation. You can use this method to launch an agent more frequently from your foreground application or from the agent itself in order to test the agent execution. This method should only be used during development. You should remove calls to this method from your production application.
This would imply that you cannot use LaunchForTest outside of testing. Strangely enough, it's not blocked by the automatic API checker, nor is it on the unsupported API list.
Still, for signed applications (ones downloaded from the Marketplace), the LaunchForTest call does not seem to work as hoped, as the documentation has suggested. This is unfortunate, but consistent with the documentation, which is good. And it works in homebrew apps, if anyone still cares about that. Not Microsoft, anyway.
You can download the sample code for this experiment here. Have fun!