GHI FEZ Cream

Thread.Sleep equivalent in UWP

Wanted to share a quick solution to an issue I ran into while working on a Universal Windows Platform (UWP) app for my Raspberry Pi 2.

Background

I was building an app to read sensor data from a .NET Gadgeteer TempHumidity module using the GHI Electronics FEZ Cream, which is a HAT (Hardware Attached on Top) for the Raspberry Pi 2 that allows the use of Gadgeteer modules. In my case, I’m running Windows 10 IoT Core on my Pi 2, so that I can stick with programming in C#. The original driver included a call to Thread.Sleep, which it turns out is not available in a UWP app.

For Gadgeteer modules that are directly supported (i.e. with drivers that have already been ported to work with Windows 10 IoT Core), integrating them into a UWP project is as simple as downloading the relevant NuGet packages. However, in my case, it turned out that the temperature and humidity sensor I was using was an older model which was not directly supported. The good news is that since GHI makes their Gadgeteer mainboard and driver code available on Bitbucket, it was easy to find the driver code for the sensor I’m using and work on a port to work on the Pi.

The Problem

The trouble that I ran into is that there are some differences in the programming model between the .NET Micro Framework (which is the basis for .NET Gadgeteer programming) and the UWP model which is used on Windows 10 IoT Core. The important difference, as noted above is that the latter does not support the use of Thread.Sleep to pause execution of a program. The Gadgeteer driver for the sensor I am using uses Thread.Sleep(1) to provide a 1ms pause as part of the code that reads the temperature and humidity data from the sensor v9ia a digital IO pin.

A quick Bing search later, I thought I had the answer (I’d link to the post, but the site appears to be down, unfortunately), which was to substitute:

await Task.Delay(1)

for the call to Thread.Sleep. While this does provide close to the same functionality, that particular syntax requires the containing method to be marked as async, and when I tried that, I found that my entire app ended up hanging. Given that the hardware responds very quickly, there’s no good reason to make the measurement functions async, so I wanted to avoid that anyway.

The Solution

The solution turned out to be quite simple, and was sitting right in front of me, in the form of one of the other drivers in GHI’s Bitbucket repo. Just use

Task.Delay(1).Wait();

The call to Task.Delay is a static method that returns a Task. The Wait method is an instance method, so in order to call it directly I’d need to create an instance of Task. Passing an integer value to Delay creates a Task that will complete after the specified number of milliseconds, while Wait says to have the calling thread wait until the Task on which it is called completes.

That may sound complex, but the effective result is basically the same as calling Thread.Sleep(1), or at least it’s certainly close enough for my purposes. After changing the ported driver code to use Task.Delay(1).Wait(), the driver worked properly and I was able to display the current temperature and humidity as reported by the sensor, as shown below.

Screenshot of TempHumid module in a UWP app

Granted, not my most inspired UI ever, but the first step was getting data, and that much is now done. Now it’s on to the cloud…

For those interested…here’s the ported code for the driver. It required very few changes to use with a UWP app…really, just the change described above.

You may also enjoy:

2 thoughts on “Thread.Sleep equivalent in UWP”

  1. Note that calling Wait() on a task can be extremely dangerous in a regular app with a UI thread and synchronization context. This is an easy way to deadlock your app, so use with caution.

    1. That’s a fair point, and thanks for bringing it up. Definitely something to be cautious with. Much better, generally, to stick with the async model.

      In my case, both because the delay is so small, and the function was already blocking in the driver being ported, there’s less concern about blocking.

      Thanks for the comment!

Comments are closed.