尝试更新 ViewModel 中的 Ui 属性时 DispatcherQueue null
Posted
技术标签:
【中文标题】尝试更新 ViewModel 中的 Ui 属性时 DispatcherQueue null【英文标题】:DispatcherQueue null when trying to update Ui property in ViewModel 【发布时间】:2021-12-20 16:40:06 【问题描述】:在桌面应用程序中的 WinUI 3 中,我有一个要更新的属性,该属性通过 x:Bind
绑定到 UI。
我想像在 WPF 中那样使用Dispatcher
来进入 UI 线程,并避免在更新道具时出现线程错误:
System.Runtime.InteropServices.COMException: 'The application called an interface that was marshalled for a different thread. (0x8001010E (RPC_E_WRONG_THREAD))'
当我尝试时,我只是不确定如何在 WinUI 3 中做到这一点
DispatcherQueue.GetForCurrentThread().TryEnqueue(() =>
AeParty.OnSyncHub = false; // Prop bound in ui using x:Bind
);
我收到此错误
DispatcherQueue.GetForCurrentThread()
为空
我也试过了:
this.DispatcherQueue.TryEnqueue(() =>
AeParty.OnSyncHub = false;
);
但它不会编译:
然后我发现this GitHub问题,所以我尝试了:
SynchronizationContext.Current.Post((o) =>
AeParty.OnSyncHub = false;
, null);
这可行,但为什么我不能在我的 VM 中使用 Dispatcher 进入 UI 线程?
【问题讨论】:
【参考方案1】:DispatcherQueue.GetForCurrentThread()
仅在实际具有DispatcherQueue
的线程上调用时返回DispatcherQueue
。如果您在后台线程上调用它,则确实不会返回 DispatcherQueue
。
所以诀窍是在 UI 线程上调用该方法并将返回值存储在一个变量中,然后您可以从后台线程中使用该变量,例如:
public sealed partial class MainWindow : YourBaseClass
public MainWindow()
this.InitializeComponent();
public ViewModel ViewModel get; = new ViewModel();
public class ViewModel : INotifyPropertyChanged
private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
public ViewModel()
Task.Run(() =>
for (int i = 0; i < 10; i++)
string val = i.ToString();
_dispatcherQueue.TryEnqueue(() =>
Text = val;
);
Thread.Sleep(2000);
);
private string _text;
public string Text
get return _text;
set _text = value; NotifyPropertyChanged(nameof(Text));
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
【讨论】:
以上是关于尝试更新 ViewModel 中的 Ui 属性时 DispatcherQueue null的主要内容,如果未能解决你的问题,请参考以下文章
从事件更新 Viewmodel - PropertyChangedEventHandler 为空?
来自事件处理程序的 ReactiveUI MVVM 更新属性
更新 ViewModel 时如何防止 Kendo UI Grid 多次重新绑定