10

In WPF all controls inherit DispatcherObject & its easy to get to the Dispatcher.

How would I get the DispatcherQueue using WinUI 3 Windows App SDK and use it in a ViewModel?

EDIT

My implementation which expands on mm8's most appreciated answer.

Create a Property in my ViewModel

public Microsoft.UI.Dispatching.DispatcherQueue TheDispatcher { get; set; }

Then grab the dispatcher in my MainPage.xaml.cs codebehind MainPage_Loaded event

ViewModel.TheDispatcher = this.DispatcherQueue;

Now I have the dispatcher n my VM so its easy to use from the VM:

TheDispatcher.TryEnqueue(() =>
{
     // some ui thread work
});

Note: I didnt post this as an answer as there is one, this is my implementation to help anyone interested.

tinmac
  • 2,357
  • 3
  • 25
  • 41

3 Answers3

23

Call the DispatcherQueue.GetForCurrentThread() API on the dispatcher thread.

If you create your view models on the dispatcher thread, you could call the method in the constructor or directly in the initializer as I demonstrated in your other question.

If you create your view models on a background thread, you will have to inject them with a DispatcherQueue that you create before on an actual dispatcher thread, e.g.:

DispatcherQueue dispatcherQueue = DispatcherQueue.GetForCurrentThread();

Task.Run(() => 
{
    ViewModel vm = new ViewModel(dispatcherQueue);
    ...
});
mm8
  • 163,881
  • 10
  • 57
  • 88
  • 5
    I cannot upvote this answer enough. I am shocked at how difficult it is to find this guidance elsewhere, say, in MS docs, which don't even have the namespace updated properly. Thank you. Anyone else coming here READ THIS ANSWER CAREFULLY. You must call GetForCurrentThread() on the UI thread and then reference it for later use from other threads! – biomiker Jun 29 '22 at 18:06
  • in what case i would use `DispatcherQueue.TryEnqueue(() => { Your code });` and `Task.Run(()=>{ your code });` lets say i have a loop of 1000 view models and i call . public async Task DoWork() on each vm, i can do it either loop through them and just do vm.DoWork(); (without await) or dispatcherQueue.TryEnqueue(async () => { await vm.DoWork(); }); which way is prefered and why ? lest say DoWork() does some long job and then updates a property that calls OnPropertyChanged(); – IronHide Jul 06 '23 at 11:53
3

Yes, getting DispatcherQueue is different from WPF, it is something like that in WinUI3:

var dispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread();

After that you can use TryEnqueue method.

demonplus
  • 5,613
  • 12
  • 49
  • 68
3

I can understand your pain while using WINUI-3 If you are in threadworkerPool and if you want to go back to the main thread Dispatcher will not be supported by WINUI-3 as of now. Instead of that use

Microsoft.UI.Dispatching.DispatcherQueue.TryEnqueue(() => {
         Your code 
    });   

I have wasted a lot of time on this, In the last I got this, hope this will work for you as well.

Satyam Mishra
  • 333
  • 3
  • 10