【问题标题】:New Thread with INotifypropertyChanged or ObservableObject for uptade the View dont work in WinUi 3用于更新视图的 INotifypropertyChanged 或 ObservableObject 的新线程在 WinUi 3 中不起作用
【发布时间】:2022-08-03 00:29:11
【问题描述】:

当我执行更新屏幕()函数,当在 TextLabel 字符串中设置新值时会引发异常。此异常在代码后面的图中演示。

当我通过调用屏幕更新时发生此错误INotifyPropertyChanged接口或通过方法可观察对象类,创建一个新线程后。

我的代码:

public class PageInicialViewModel : ObservableObject
{
    private int cont = 0;
    private string _textLabel = 0.ToString();
    public string TextLabel
    {
        get => _textLabel;
        set => SetProperty(ref _textLabel, value);
    }

    public void  updateScreen()
    {
        Task.Factory.StartNew(updateTextLabel);
    }

    public void updateTextLabel()
    {
        while (true)
        {
            cont++;
            TextLabel = cont.ToString();
            Thread.Sleep(TimeSpan.FromSeconds(1));
        }        
    }
}

错误:System.Runtime.InteropServices.COMException:\'应用程序调用了一个为不同线程编组的接口。 (0x8001010E (RPC_E_WRONG_THREAD))\'

    标签: c#


    【解决方案1】:

    UI 只能从主线程(它是用它创建的)更新是一个古老的问题。 (通过一个或其他 ui 框架中不同程度的容忍度。)

    WinUI 的解决方案看起来像这样。

    public class PageInicialViewModel : ObservableObject
    {
        private int cont = 0;
        private string _textLabel = 0.ToString();
        private Microsoft.UI.Dispatching.DispatcherQueue _dispatcherQueue;
    
        public PageInicialViewModel()
        {
            // must be called on ui thread
            _dispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread(); 
        }    
    
        public string TextLabel
        {
            get => _textLabel;
            set => SetProperty(ref _textLabel, value);
        }
    
        public void  updateScreen()
        {
            Task.Factory.StartNew(updateTextLabel);
        }
    
        public void updateTextLabel()
        {
            while (true)
            {
                cont++;
                _dispatcherQueue.TryEnqueue(() =>
                {
                    TextLabel = cont.ToString();
                });
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }        
        }
    }
    

    仅供参考,在 WPF 中也可以通过以下方式实现:

    System.Windows.Application.Current.Dispatcher.Invoke(() =>
    {
    
    });
    

    如果您搜索这些术语,您可以找到很多关于一般技术原理的解释和文章。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-18
      • 2014-05-24
      • 1970-01-01
      • 1970-01-01
      • 2020-07-31
      相关资源
      最近更新 更多