我正在尝试显示一个winui对话框 - 即一个源于 contentDialog - 从背景线程执行的代码中,我需要等待对话框的结果。
我知道,只有通过某种调度程序将该代码返回给UI线程的某种调度程序才能显示对话框。
这是以当前形式显示我的对话框的方法:
public async Task<MyDialogResult> ShowMyDialogAsync(MyViewModel viewModel, string primaryButtonText, string closeButtonText)
{
// EXCEPTION OCCURS HERE WHEN CALLING FROM NON UI-THREAD
MyDialog dialog = new MyDialog(); // This class derives from ContentDialog
// Set dialog properties
dialog.PrimaryButtonText = primaryButtonText;
dialog.CloseButtonText = closeButtonText;
dialog.ViewModel = viewModel;
dialog.XamlRoot = _xamlRoot;
await dialog.ShowAsync();
return dialog.ViewModel.MyDialogResult;
}
请注意,我需要此对话框的结果,该对话框由用户输入。这就是为什么该方法具有 task&lt; myDialogresult&gt;
的返回值的原因。
在进行研究时,我遇到了这个答案,它是指等待从背景线程发送的UI任务来自Microsoft。
他们在那里使用方法 runAsync
将转换为方法 runtaskAsync&lt; t&gt;
。
可以在 coredispatcher 类。
我的问题是:我无法尝试这种方法,因为访问它时的CoredisPatcher属性在运行时似乎总是为零(例如,从我的MainWindow类)。
这是运行时我的MainWindow实例的屏幕截图:
根据此文章,“调度程序”为Null似乎是一个设计选择。
唯一可用的类似属性是调度员。但这只有方法。
但是我不知道如何以我需要的方式使用它,这不仅是在UI线程上执行代码,而且还等待其完成,因此代码可以以受控的方式运行。
有人知道如何使用某种调度程序在Winui contentDialog
中显示如何显示方法并等待对话框的结果?
I am trying to show a WinUI dialog - i.e. a class that derives from ContentDialog - from code that executes from a background thread and I need to wait for the result of the dialog.
I know that showing a dialog from a background thread is only possible with some kind of dispatcher that dispatches this code back to the UI thread.
This is the method that shows my dialog in its current form:
public async Task<MyDialogResult> ShowMyDialogAsync(MyViewModel viewModel, string primaryButtonText, string closeButtonText)
{
// EXCEPTION OCCURS HERE WHEN CALLING FROM NON UI-THREAD
MyDialog dialog = new MyDialog(); // This class derives from ContentDialog
// Set dialog properties
dialog.PrimaryButtonText = primaryButtonText;
dialog.CloseButtonText = closeButtonText;
dialog.ViewModel = viewModel;
dialog.XamlRoot = _xamlRoot;
await dialog.ShowAsync();
return dialog.ViewModel.MyDialogResult;
}
Please note that I need some result from this dialog which is entered by the user. That is why the method has a return value of Task<MyDialogResult>
.
While doing my research I came across this answer, which refers to the article Await a UI task sent from a background thread from Microsoft.
There they use a method RunAsync
which gets transformed into a method RunTaskAsync<T>
.
The RunAsync
method can be found on the CoreDispatcher class.
My problem is: I am unable to try this approach, because the CoreDispatcher property seems always to be null at runtime when accessing it (from my MainWindow class for example).
Here is a screenshot of my MainWindow instance during runtime:

According to this article, "Dispatcher" being null seems to be a design choice.
The only similar property available is a DispatcherQueue. But this only has the method TryEnqueue.
But I do not know how to use it in they way I need, which is not only to execute the code on the UI thread but also wait for its completion, so code can run after it in a controlled manner.
Does anyone know how an approach how to show in WinUI ContentDialog
using some kind of dispatcher and wait for the result of the dialog?
发布评论
评论(2)
我让它起作用。
第1部分
解决方案的第一部分是发现确实包含一个nuget软件包“ communitytoolkit.winui”,它确实包含一个类
dispatcherqueextensions
具有用于扩展方法的 类,在某些“ enqueueasync”方法中。此 dispatcherqueueextensions文档是相同的。
使用正在使用的“ communityToolkit.winui” nuget软件包,您可以写下代码:
第2部分
第二部分重点是问题,即在背景线程上运行的代码必须不仅必须在上面调用代码UI线程,但也要等待其完成(因为在我的情况下需要对话框中的用户数据)。
我找到了一个问题“ runAsync-我如何等待UI线程上的工作完成? -i-await-the-the-the-ui-thread“> the-ui-thread”>在stackoveflow上。
在此答案用户“ mike”介绍了一个解决此问题的类
dispatchertAskextensions
。我将代码重写以使用类型
dispatcherqueue
而不是coredispatcher
(如我发现的那样,在Winui中不支持)。用法
此示例使用具有私有字段的类
_disPatcherqueue
typedispatcherqueue
和一个私有字段_xamlroot
UIELEMENT
需要提前设置。现在我们可以这样使用:
I got it working.
Part 1
The first part of the solution for me was to find out that there is a Nuget package "CommunityToolkit.WinUI" that does contain a class
DispatcherQueueExtensions
which has extension methods for the DispatcherQueue class, among those some "EnqueueAsync" methods.This DispatcherQueueExtensions documentation refers to UWP, but the usage for WinUI is identical.
With the "CommunityToolkit.WinUI" Nuget package in use, you can write code like this:
Part 2
The second part focuses on the problem, that the code running on the background thread must no only invoke code on the UI thread, but also wait for its completion (because user data from a dialog is required in my case).
I found a question "RunAsync - How do I await the completion of work on the UI thread?" here on stackoveflow.
In this answer the user "Mike" introduces a class
DispatcherTaskExtensions
which solves this problem.I rewrote the code to work with instances of type
DispatcherQueue
instead ofCoreDispatcher
(which is not supported in WinUI, as I discovered).Usage
This example uses a class that has a private field
_dispatcherQueue
of typeDispatcherQueue
and a private field_xamlRoot
of typeUIElement
that need to be set in advance.Now we can use this like so:
正如您已经发现的那样,您应该能够在 communityToolkit.winui nuget软件包。
只需确保您调用
dispatcherqueue.getForCurrentThread()
方法,以获取UI线程上dispatcherqueue
的引用,并且您 specify axamlroot
contentdialog 一种或另一种方式。以下是一个工作示例。
As you have already discovered yourself, you should be able to use the
DispatcherQueueExtensions
in the CommunityToolkit.WinUI NuGet package.Just make sure that you call the
DispatcherQueue.GetForCurrentThread()
method to get a reference to theDispatcherQueue
on the UI thread and that you specify aXamlRoot
for theContentDialog
one way or another.Below is a working example.