允许从任何非 UI 线程引发通知更改的属性发生 UI 绑定
绑定属性时,必须始终在 UI 线程上发出属性更改通知,否则会出现运行时异常。 这会导致 UI 渗入您的视图模型和模型,以便您可以在正确的线程上引发,这反过来又会阻止您使用 .NET Standard 库中的 INPC(除非您想进入 bait'n'switch) .
此外,您可能在一帧中多次更改属性,因此您可能跳到 UI 线程的次数可能比实际需要的次数多(只需将属性标记为“脏”,然后在下一个渲染通道。
所有这些都会导致明显额外的代码复杂性并且更容易出错。
这也导致了 WinUI 3.0 中的一个问题,因为我们现在有两个 UI 线程:旧版 UWP 和 WinUI 线程:我应该提高哪一个?
线程问题当然是有效的,但我不相信这最终真的是一个问题。 在 UI 更新之前触发多个 INPC 事件并不重要,因为只有最后一个事件才重要。 这与现有代码多次切换到 UI 线程没有什么不同。 一旦第一个切换到 UI 线程,该属性可能已经更新了很多次,因此最后一个获胜。
自然地,在读取值时需要一个短锁,以防止设置脏标志,因此如果在读取属性的同时更新属性,则在下一帧发生第二轮 UI 更新。
事实上,如果一个值例如从 false 变为 true,然后又变为 false,则 Dependency Property 已经足够智能,可以检测到该值没有改变,并且可以通过不因该属性而导致新的渲染传递来进行优化不变。
这是一个非常有效的问题,感谢您提出这个问题。 框架中对 DPs 的线程亲和性支持可能不是一个大问题,但对于 INPC 的实现者来说可能是一个很好的问题。
如果某些代码能够从非 UI 线程引发属性更改,这也意味着属性的支持代码可能会从后台线程更改。 它可以使用锁来保护它,但是双向绑定可能会成为一个问题,因为它们可能会使属性更改链死锁。
INPC还有一个最大的问题,就是事件发起时缺乏“当前”价值。 可能存在属性未正确同步的情况(例如, SelectedIndex
和ItemsSource
未同步更新并且SelectedIndex
失去其值),或者由于由属性状态(例如文本框更改和正则表达式过滤器)。
这就带来了 INCC 的问题,即整个收藏品都需要得到适当的保护。 例如,您可能会引发一个引用已移动或不再存在的项目的事件。
我并不是说这个问题没有解决方案(肯定有),但是 IPNC 侦听器线程关联性更改不足以在接口的两端轻松解决这个问题。
WPF 已经解决了这个问题,所以也许只是从那里提取解决方案?
很好的建议。 我们为 CollectionChanged 事件执行此操作(有点意外......),我们应该能够为 NotifyPropertyChanged 执行相同操作。
最有用的评论
这是一个非常有效的问题,感谢您提出这个问题。 框架中对 DPs 的线程亲和性支持可能不是一个大问题,但对于 INPC 的实现者来说可能是一个很好的问题。
如果某些代码能够从非 UI 线程引发属性更改,这也意味着属性的支持代码可能会从后台线程更改。 它可以使用锁来保护它,但是双向绑定可能会成为一个问题,因为它们可能会使属性更改链死锁。
INPC还有一个最大的问题,就是事件发起时缺乏“当前”价值。 可能存在属性未正确同步的情况(例如,
SelectedIndex
和ItemsSource
未同步更新并且SelectedIndex
失去其值),或者由于由属性状态(例如文本框更改和正则表达式过滤器)。这就带来了 INCC 的问题,即整个收藏品都需要得到适当的保护。 例如,您可能会引发一个引用已移动或不再存在的项目的事件。
我并不是说这个问题没有解决方案(肯定有),但是 IPNC 侦听器线程关联性更改不足以在接口的两端轻松解决这个问题。