• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

尝试更新ViewModel中的Ui属性时DispatcherQueue为空

用户头像
it1352
帮助8

问题说明

在桌面应用程序的WinUI 3中,我有一个要更新的属性,该属性通过x:Bind绑定到该UI。

我希望像在WPF中一样使用Dispatcher进入UI线程,并避免在更新道具时IM遇到的线程错误:

System.Runtime.InteropServices.COMException: 'The application called an interface that was marshalled for a different thread. (0x8001010E (RPC_E_WRONG_THREAD))'

我只是不确定在WinUI3中如何操作,当我尝试时

DispatcherQueue.GetForCurrentThread().TryEnqueue(() =>
{
    AeParty.OnSyncHub = false; // Prop bound in ui using x:Bind
});

我收到此错误

DispatcherQueue.GetForCurrentThread()为空

我也试过了:

this.DispatcherQueue.TryEnqueue(() =>
{
    AeParty.OnSyncHub = false;
});

但无法编译:

然后我发现thisGitHub问题,所以我尝试:

SynchronizationContext.Current.Post((o) =>
{
    AeParty.OnSyncHub = false;

}, null);

这是可行的,但为什么我无法在我的VM中使用调度程序进入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));
    }
}

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /reply/detail/tanccc
系列文章
更多 icon
同类精品
更多 icon
继续加载