Run code on UI thread in WinRT

.NetMultithreadingWindows 8Windows RuntimeDispatcher

.Net Problem Overview


How can I run code on the UI thread in WinRT (Windows 8 Metro)?

The Invoke method does not exist.

.Net Solutions


Solution 1 - .Net

It's easier to directly get the CoreWindow from the non-UI thread. The following code will work everywhere, even when GetForCurrentThread() or Window.Current returns null.

CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
    <lambda for your code which should run on the UI thread>);

for example:

CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
    () =>
    {
        // Your UI update code goes here!
    });

You'll need to reference Windows.ApplicationModel.Core namespace:

using Windows.ApplicationModel.Core;

Solution 2 - .Net

Use:

From your UI thread, execute:

var dispatcher = Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher;

From your background (non UI thread)

dispatcher.RunAsync(DispatcherPriority.Normal, 
    <lambda for your code which should run on the UI thread>);
 

That should work on both CP and later builds.

Solution 3 - .Net

Use:

this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => Frame.Navigate(typeof(Welcome), this));

It works for me.

Solution 4 - .Net

This is a much easier way in my opinion.

Get the TaskScheduler associated with the UI.

    var UISyncContext = TaskScheduler.FromCurrentSynchronizationContext();

Then start a new Task and on the above UISyncContext.

    Task.Factory.StartNew(() => { /* Do your UI stuff here; */}, new System.Threading.CancellationToken(), TaskCreationOptions.PreferFairness, UISyncContext);

Solution 5 - .Net

DispatcherTimer is also an option.

I used it for code that must be run in Xaml-designer (CoreWindow.Dispatcher,... are not available in UWP-designer)

var localTimer = new DispatcherTimer
{
    Interval = TimeSpan.FromMilliseconds(0)
};
localTimer.Tick += (timer, e) =>
{
    (timer as DispatcherTimer).Stop();
    action();
};
localTimer.Start();

Disclaimer:
I should note that this should be a last-resort option if every other fails.

Solution 6 - .Net

On UWP, I was having problem trying to set the Source property of CaptureElement control (that is defined in XAML), it was complaining about being prepared at different thread, even though I was trying to set it from code that was invoked via a Page_Loaded event handler. I ended up using this to work around it:

previewControl.Dispatcher.TryRunAsync(CoreDispatcherPriority.Normal, () => {
   previewControl.Source = _mediaCapture;
}).GetAwaiter().GetResult();

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionoferView Question on Stackoverflow
Solution 1 - .NetCœurView Answer on Stackoverflow
Solution 2 - .NetLarry OstermanView Answer on Stackoverflow
Solution 3 - .NetMangesh OzardekarView Answer on Stackoverflow
Solution 4 - .NetDeebView Answer on Stackoverflow
Solution 5 - .NetDavid RettenbacherView Answer on Stackoverflow
Solution 6 - .NetGeorge BirbilisView Answer on Stackoverflow