c# - 来自不同线程的 WPF 和 NotifyPropertyChanged

标签 c# wpf multithreading

我对 WPF 非常熟悉,但有一件事困扰着我。我正在使用 ReactiveUI 引发 INotifyPropertyChanged 事件。我有两个地方与此类似:

 public UiModel UiModel
            {
                get { return _uiModel; }
                set { this.RaiseAndSetIfChanged(ref _uiModel, value); }
            }

    public void Run()
    {
      UiModel = GetUIModel();
    }

其中 Run() 是这样调用的 await Task.Run(()=>Run()); 并且 UiModel 是绑定(bind)的在 XAML 中。 那么基本上应该发生什么 -> 如果在不同的线程上调用 Run() 函数,它应该抛出一个跨线程异常,不是吗?我在代码中有两个地方,在一个地方它总是抛出异常,在第二个地方永远不会抛出异常。我已经比较了线程 ID,并且在这两个地方 Run() 都没有在 UI 线程上运行。为什么会这样? 在它不抛出异常的地方,我将它绑定(bind)到 UserControl 中的依赖属性,然后我使用普通绑定(bind)将它绑定(bind)

抛出异常:{“调用线程无法访问此对象,因为另一个线程拥有它。”}

看来我已经找到了针对这种特定情况的答案。异常不是由 UiModel 抛出的,它是绑定(bind)的,但 UiModel 也用于 ReactiveUI 验证。如果我不从 UI 更新它,它将尝试从导致该异常的不同线程更新 CanExecuteChanged。尽管如此,我的问题仍然是一样的——为什么我可以从不同的线程更新 UI 而没有跨线程异常?我在 ReactiveUI PropertyChanged 调用中看不到调度程序调用。

最佳答案

这方面存在一些恼人的不一致。以下是您可以和不能从工作线程执行的操作列表。

引发跨线程异常:

  • 修改 DependencyProperty在控件上
  • 提高 ICommand.CanExecuteChanged事件
  • 提高 INotifyCollectionChanged.CollectionChanged事件,通常来自 ObservableCollection<T> 的实例

不抛出异常:

  • 提高 INotifyPropertyChanged.PropertyChanged事件,通常来自 View 模型绑定(bind)

我确信 WPF 不自动调用第一个列表是有充分理由的,但我想不出它可能是什么。

我对处理服务事件的建议是:

  1. 维护对 SynchronizationContext 的引用从 UI 线程捕获(可能在这里对您最有用)。
  2. 使用中介服务在 UI 线程上调用应用程序事件处理程序

关于c# - 来自不同线程的 WPF 和 NotifyPropertyChanged,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38452688/

相关文章:

python - 线程与事件循环——网络编程(语言无关)

c# - Windows 8 计算机无法迭代工作组成员?

c# - 使用 C# 和 Powerpoint OpenXML,是否可以更改文本的字体大小和颜色

wpf - 有没有办法在WPF中使用澳大利亚英语词典

c# - 具有 Windows 身份验证的 WPF 应用程序

python - 如果我永远同时运行两个或多个函数,它们是否访问相同的内存?

python - 将线程模块与 atexit 处理程序一起使用时出现异常 KeyError : KeyError(139697538152192, )

c# - C# 'for' 循环中的多重初始化

c# - 多种属性合二为一?

c# - c#中特定代码的定期执行