gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-03 23:12:47 25 4
gpt4 key购买 nike

我对 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com