Correct way to get the CoreDispatcher in a Windows Store app
Solution 1
This is the preferred way:
Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
// Your UI update code goes here!
});
The advantage this has is that it gets the main CoreApplicationView
and so is always available. More details here.
There are two alternatives which you could use.
First alternative
Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().CoreWindow.Dispatcher
This gets the active view for the app, but this will give you null, if no views has been activated. More details here.
Second alternative
Window.Current.Dispatcher
This solution will not work when it's called from another thread as it returns null instead of the UI Dispatcher. More details here.
Solution 2
For anyone using C++/CX
Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
CoreDispatcherPriority::Normal,
ref new Windows::UI::Core::DispatchedHandler([this]()
{
// do stuff
}));
Solution 3
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
CoreDispatcherPriority.Normal,
() => { // your code should be here});
Solution 4
While this is an old thread, I wanted to draw attention to a possible issue developers may run across which impacted me and made it extremely difficult to debug in large UWP apps. In my case, I refactored the following code from the suggestions above back in 2014 but would occasionally be plagued with the occasional app freezes that were random in nature.
public static class DispatcherHelper
{
public static Task RunOnUIThreadAsync(Action action)
{
return RunOnUIThreadAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, action);
}
public static async Task RunOnUIThreadAsync(Windows.UI.Core.CoreDispatcherPriority priority, Action action)
{
try
{
await returnDispatcher().RunAsync(priority, () =>
{
action();
});
}
catch (Exception ex)
{
var noawait = ExceptionHandler.HandleException(ex, false);
}
}
private static Windows.UI.Core.CoreDispatcher returnDispatcher()
{
return (Windows.UI.Xaml.Window.Current == null) ?
CoreApplication.MainView.CoreWindow.Dispatcher :
CoreApplication.GetCurrentView().CoreWindow.Dispatcher;
}
}
From the above, I had used a static class to allow the calling of the Dispatcher through-out the application - allowing for a single call. For 95% of the time, everything was fine even through QA regression but clients would report an issue every now and then. The solution was to include the call below, not using a static call in the actual pages.
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
});
This is not the case when I need to ensure the UI Thread was called from App.xaml.cs or my Singleton NavigationService which handled pushing/popping on to the stack. The dispatcher apparently was losing track of which UI Thread was called, since each page has it's own UI thread, when the stack had a variety of Messages triggering from the MessageBus.
Hope this helps others that may be impacted and it is also where I think each platform would do a service to their developers by publishing a complete project covering the best practices.
Related videos on Youtube
lysergic-acid
Software Engineer, Game Developer, Cat Owner Blogging @ http://www.tallior.com Check out my gigs @ http://www.fiverr.com/lysergide
Updated on July 08, 2022Comments
-
lysergic-acid almost 2 years
I'm building a Windows Store app, and I have some code that needs to be posted to the UI thread.
For that, i'd like to retrieve the CoreDispatcher and use it to post the code.
It seems that there are a few ways to do so:
// First way Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().CoreWindow.Dispatcher; // Second way Window.Current.Dispatcher;
I wonder which one is correct? or if both are equivalent?
-
Nate Diamond almost 11 yearsBoth are kind of correct, but it will be null if you're not accessing it from something that already has access to the Dispatcher. If you want to use it in, say, a ViewModel or Controller, then you'll need to store off the Dispatcher, generally as a static Property in your App.xaml.cs or IOC controller, and set it from the first page that you have load.
-
-
Robert Oschler about 10 yearsI tried this but when I trace the code, the delegate code is still executing on a Worker thread and not the "Main Thread".
-
Illidan about 10 yearsPlease note that (at least in Windows 8.1) DispatcherPriority is now CoreDispatcherPriority
-
Yury Schkatula over 6 yearsThis would work as long as we have single ASTA (application single-threaded apartment). In case we introduce "sharing target" feature, there are multiple ASTAs (each one with its own dispatcher). And then CoreApplication.MainView can be null (because its ASTA is not initialized yet). Be aware!
-
sjb-sjb over 6 yearsI have seen CoreApplication.MainView cause my program to hang when called from a non-UI thread. I had to stash the CoreApplication.MainView.CoreWindow.Dispatcher at startup in order to access it later.
-
Richard Chambers almost 6 years"For authoring and consuming Windows Runtime APIs using C++, there is C++/WinRT. This is Microsoft's recommended replacement for the Windows Runtime C++ Template Library (WRL) and C++/CX." C++/WinRT
-
Gregory Bologna over 2 yearsThis worked for me in UWP app as long as I used discard operator. _ = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => someMethod("abc"));
-
MAXE over 2 years@GregoryBologna interesting...but I think yours is just a syntax issue...any lamba expression can be used in {} form: docs.microsoft.com/en-us/dotnet/csharp/language-reference/…