Windows Store app Development Snack: The vastness of CPU time

I’ve written in a previous post (What do you get from being a lock screen app?) about how background processing has a limited amount of time to do its processing, what the odd unit of measurement is (the CPU second), and the overflow bucket. Even with all that, it’s hard to understand what you can accomplish in the time available, so let’s look at what an app I built Bing my lockscreen does in its time.

In short, what I hope you take away from this is that you do get a decent amount of time—and that with careful planning, you can do a lot!


The Process

First off, Bing my lockscreen—since it uses a timer—requires lock screen permissions, which means it gets at least 2 CPU seconds every fifteen minutes, plus overflow from the bucket.

The first thing that happens is we get a deferral object (similar to what was explained in Async & Sharing), since we need to use async in the background task. We then go to the RoamingSettings values to get a boolean (which needs to be cast, since RoamingSettings is a Dictionary<string, object>) to see if the user has disabled automatic updates. Now, assuming the user hasn’t disabled automatic updates, we connect to a website using the HttpClient & HttpClientHandler classes and pull down some JSON as a string, converting it to an object using Windows.Data.Json.JsonObject.

Aside: If I felt too tight on CPU, I might swap to the AWESOME Json.NET, which has better parsing performance.

If all that worked (with minimal logging and status checks happening in between), I use a touch of LINQ to get the first image from the IEnumerable collection where it’s stored internally. I then check the URL of the image against a value stored in LocalSettings, since I don’t want to update the lock screen with the same image multiple times. If the image is different, I download it from Bing to the TemporaryFolder, check that the file size is greater than 0, and if it is, call SetImageFileAsync to change the lock screen. Otherwise, I delete the damaged file. Downloading is far more complex than it first appears, as I need to handle proxies, fall back to the 1366×768 resolution image if I can’t get 1920×1200, and ensure everything is written to disk before the lock screen is set (I had some issues with I/O buffers in earlier versions that caused minor corruption because the images weren’t fully flushed to disk!).

Aside: An important thing to remember is that CPU seconds are the time the CPU actually works—when it’s idle, say because you’re doing something I/O-bound like a download, it doesn’t count!

Next, I store the result of this in the log—a container in LocalSettings (so the first time it’s run, we create that container too!)—and store the URL of the newly changed image. The process continues similarly for the live tile! We check if the last live tile update is the same by comparing the image URL (again, against a value stored in LocalSettings). I then use TileNotification and TileUpdateManager to send the tile update. Since tiles support remote URLs for images, I don’t need to download the tile image in this case. Finally, I update LocalSettings for the updated tile!


Line Count

If you count the lines of code executed for this—and I’m excluding blank lines, namespace declarations, and comments—really, just the code that actually runs—it’s about 190 lines of C#. Far more than you might think.


More Stats!

I used the always amazing NDepend to generate more stats on the assembly that does all the background processing: