我在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
在 XAML
中被绑定。那么基本上应该会出现跨线程异常,如果在不同的线程上调用 Run()
函数,对吗?我在代码中有两个地方,其中一个总是抛出异常,而另一个地方则从未抛出过异常。我已经比较了线程 ID,在两个地方 Run()
都不是在 UI 线程上运行。为什么会这样呢?
抛出的异常信息:{"The calling thread cannot access this object because a different thread owns it."}
看起来我已经在这个特定的情况下找到了答案。异常并不是由 UiModel 和它的绑定引起的,而是由 ReactiveUI 验证中使用了 UiModel 导致的。如果我不从 UI 更新它,它将尝试从不同的线程更新 CanExecuteChanged,从而导致异常。然而我的问题仍然存在——为什么我可以在不同的线程上更新 UI,却没有出现跨线程异常?我在 ReactiveUI PropertyChanged 调用中没有看到 Dispatcher 调用。