Observing on the Dispatcher Thread with Rx
In my last post, I talked about handling the FileCompleted
event from an AudioFileInputNode
in a UWP application. Since this event is raised from a background thread, it’s important to get back onto the Dispatcher thread before making any updates to the overall AudioGraph
, or changing the UI.
In UWP, this can be done by calling RunAsync
on the Dispatcher. (By the way if you’re in a ViewModel then you can get at the Dispatcher with the rather cumbersome CoreApplication.MainView.CoreWindow.Dispatcher
static property)
private async void FileInputNodeOnFileCompleted(AudioFileInputNode sender, object args)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
// code here runs on dispatcher thread
});
}
Now this works fine, but there is a nice alternative you can use if you’re working with Reactive Extensions. Rx makes it really easy for us to say that we want to observe an event on the Dispatcher thread. We do of course need to turn the event into an Observable first, which can be done with a call to Observable.FromEventPattern
(which admittedly is a little bit cumbersome itself), but then we can say we want to observe it on the current SynchronizationContext
(which is the Dispatcher thread in UWP).
Here’s a simple example:
Observable.FromEventPattern<EventHandler, EventArgs>(
h => audioEngine.FileCompleted += h,
h => audioEngine.FileCompleted -= h)
.ObserveOn(SynchronizationContext.Current)
.Subscribe(f => OnPlaybackCompleted());
Now our event handler method OnPlaybackCompleted
will run on the correct thread. Of course, on its own this may not seem a great improvement to using Dispatcher.RunAsync
, but the benefit is that now it is an Observable, we can also make use of all the powerful composability that Rx brings.