Fixing CoreDispatcher.Invoke – How to Invoke Method in UI Thread in Windows 8 Release Preview
The Release Preview of Windows 8 broke some things but fortunately there’s a quite good migration guide available which highlight most of the changes (Word document):
Migrating your Windows 8 Consumer Preview app to Windows 8 Release Preview
Unfortunately the guide seems to have missed some changes, like the removing of CoreDispatcher.Invoke and BeginInvoke –methods.
Breaking Change between Consumer Preview and Release Preview:
The following code worked in WinRT app with Consumer Preview:
dispatcher.Invoke(CoreDispatcherPriority.Normal, (s, e) => action(), dispatcher, null);
But the Invoke-method is now gone. If it’s OK that the action is executed asynchronously in UI thread (like BeginInvoke), this seems to be the way to go in Release Preview + WinRT combination:
dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => action());
But if the invoke must happen synchronously (like Invoke), async / await can be used:
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => action());
UIDispatcher - A helper class which allows the synchronous and asynchronous execution of methods in UI thread:
Here’s a complete UIDispatcher-class which can be used to execute actions in UI thread:
using System;
using System.Threading.Tasks;
using Windows.UI.Core;
using Windows.UI.Xaml;
namespace Helpers
{
public static class UIDispatcher
{
private static CoreDispatcher dispatcher;
public static void Initialize()
{
dispatcher = Window.Current.Dispatcher;
}
public static void BeginExecute(Action action)
{
if (dispatcher.HasThreadAccess)
action();
else dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => action());
}
public static void Execute(Action action)
{
InnerExecute(action).Wait();
}
private static async Task InnerExecute(Action action)
{
if (dispatcher.HasThreadAccess)
action();
else await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => action());
}
}
}Initialization:
Call the Initialize-method at the application startup, for example in App.xaml.cs's OnLaunched-method:
// Place the frame in the current Window and ensure that it is active
Window.Current.Content = rootFrame;
Window.Current.Activate();
UIDispatcher.Initialize();Without this the UIDispatcher won't work.
Invoking actions on UI thread:
After the UIDispatcher has been initialized, the Execute-method can be used to invoke actions in UI thread synchronously and BeginExecute to invoke action asynchronously:
ThreadPool.RunAsync(operation => UIDispatcher.Execute(() => this.Test.Text = "hello!"));
Links:
Here’s a good explanation by Jon Skeet about the differences of BeginInvoke and Invoke.