我对 WPF 非常有经验,但有一件事困扰着我。我正在使用 ReactiveUI 引发 INotifyPropertyChanged 事件。我有两个类似的地方:
public UiModel UiModel
{
get { return _uiModel; }
set { this.RaiseAndSetIfChanged(ref _uiModel, value); }
}
public void Run()
{
UiModel = GetUIModel();
}
where Run()
是这样称呼的await Task.Run(()=>Run());
and UiModel
绑定在XAML
。
那么基本上应该发生什么 -> 它应该抛出一个跨线程异常,如果Run()
函数在不同的线程上调用,不是吗?我在代码中有两个地方,在一个地方它总是抛出异常,在第二个地方永远不会抛出异常。我比较了两个地方的线程 IDRun()
不在 UI 线程上运行。为什么会这样呢?
在不抛出异常的地方,我将其绑定到 UserControl 中的依赖属性,然后使用普通绑定将其绑定
抛出异常:{"The calling thread cannot access this object because a different thread owns it."}
看起来我已经找到了这种具体情况的答案。 UiModel 及其绑定不会抛出异常,但 UiModel 也用于 ReactiveUI 验证。如果我不从 UI 更新它,它将尝试从导致该异常的不同线程更新 CanExecuteChanged。尽管如此,我的问题仍然是一样的 - 为什么我可以从不同的线程更新 UI 而不会出现跨线程异常?我在 ReactiveUI PropertyChanged 调用中看不到调度程序调用。
该领域存在一些令人烦恼的不一致之处。以下是您可以和不能从工作线程执行的操作的列表。
引发跨线程异常:
- 修改一个
DependencyProperty
在控制上
- 提高
ICommand.CanExecuteChanged
event
- 提高
INotifyCollectionChanged.CollectionChanged
事件,通常来自以下实例ObservableCollection<T>
不抛出异常:
- 提高
INotifyPropertyChanged.PropertyChanged
事件,通常来自视图模型绑定
我确信 WPF 不自动调用第一个列表是有充分理由的,但我想不出它可能是什么。
我的处理建议服务活动 are:
- 维护对a的引用
SynchronizationContext
从 UI 线程捕获(这里可能对您来说最常用)。
- 使用中介服务在 UI 线程上调用应用程序事件处理程序
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)