【问题标题】:Does setting a ViewModel property have thread affinity in Xamarin Forms?在 Xamarin Forms 中设置 ViewModel 属性是否具有线程关联性?
【发布时间】:2017-02-11 20:07:09
【问题描述】:

前几天,在一次代码审查中,我看到了一些关于从工作线程设置属性的安全性问题。一位同事评论说:“此属性绑定到 UI,并且数据绑定是线程安全的。”

我使用 XF 已经有一段时间了,但一直认为这不是真的:如果我想更新绑定到 UI 的 ViewModel 属性,我必须在 UI 线程上进行这些更改。我只是花了几分钟浏览文档,除了直接操作 BindableProperties 具有线程亲和力之外,我没有看到明显的答案。这对我来说是否是阻塞的 UI 线程执行也很重要。

我可以自己做一个项目来测试它,但这类问题似乎总是间歇性的,所以我想知道我只是缺少正确的文档。

(这与调查主要发生在 Xamarin 调用堆栈中的崩溃有关。我们从工作线程引发事件,VM 处理该事件并更新一些属性。如果这是为 UI 线程安排的,可能有一些我们没有准备好的交错问题,我离解决崩溃问题更近了。如果它没有被安排在 UI 线程中......我很惊讶它工作了这么长时间。)

【问题讨论】:

    标签: mvvm xamarin.forms


    【解决方案1】:

    我使用 XF 已经有一段时间了,但一直认为这不是真的:如果我想更新绑定到 UI 的 ViewModel 属性,我必须在 UI 线程上进行这些更改。

    你是对的。 100% 正确。您可以为此使用Device.InvokeOnMainThread()

    完整地说,有一种情况无关紧要:PropertyChanged

    https://github.com/xamarin/Xamarin.Forms/blob/b645064/Xamarin.Forms.Core/BindingExpression.cs#L542

    在这种情况下,Binding 将应用于主 (UI) 线程。

    【讨论】:

    • 这似乎暗示从任何线程更新我的虚拟机安全的,因为虚拟机传统上是一个 INotifyPropertyChanged 实现。对吗?
    • 代码只涉及getter,而不是setter
    【解决方案2】:

    假设

    我们仅通过绑定与 UI 交互。所以只有setter和getter在玩。

    吸气剂

    @Stephane 在 github 中引用的代码仅表示您绑定的 getter 将在 UI 线程中调用。不多不少。

    顺便说一句,我不会依赖源代码(我的意思是:实现),而是规范才是最重要的。实现可以随时更改,如果规范没有要求,那么单元测试不会检查这一点,所以会有很大的惊喜......

    二传手

    但是仍然不清楚,您是否可以在后台线程中调用您的设置器。无论答案是肯定还是否定,都意味着需要解决更多任务。

    a) 如果您可以在任何线程中调用 setter:这意味着,您的 viewmodel 内部数据会暴露在竞争条件下,因为将从 UI 线程调用,并且 将在一个后台线程。结论:您必须使用通常的并发模式保护数据,或者使用线程安全类,另外:您的 getter 和 setter 必须是原子的。

    b) 如果你不能在任何线程中调用 setter:那么你必须使用Device.InvokeOnMainThread()。但这只是故事的一半。在后台线程的方法中,您正在修改一个 List 实例。这将由 getter 在 UI 线程中访问,当您说填充它时,您正在后台线程中同时修改它。从理论上讲,用户可能会在填充期间与 UI 交互,让绑定评估的内容,getter 被调用。

    结论:

    如果有多个线程访问相同的数据,则必须始终锁定数据。

    不管当前的源代码意味着什么,将 getter 和 setter 编组到 UI 线程的最安全方法。这不会导致显着的开销:如果执行已经在 UI 线程中,则 marshall 将不执行任何操作。

    注意:即使您将 getter 和 setter 编组到 UI 线程,您也将在后台线程中访问数据,因此防止竞争条件或使用线程安全类是必不可少的。

    【讨论】:

      猜你喜欢
      • 2017-11-25
      • 2017-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-03
      • 1970-01-01
      相关资源
      最近更新 更多