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.