MVVM INotifyPropertyChanged - 线程问题?

2023-12-24

我刚刚开始学习 MVVM 和 WPF,很抱歉提出了愚蠢的问题。

我正在使用不同的教程和示例来学习,并且我遇到了这个例子 http://www.codeproject.com/Articles/165368/WPF-MVVM-Quick-Start-Tutorial(阅读示例2)我不明白。

private void RaisePropertyChanged(string propertyName)
{
    // take a copy to prevent thread issues
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
    {
        handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

基本上,该评论对我来说没有多大意义...“复制一份以防止线程问题”。

这行:

PropertyChangedEventHandler handler = PropertyChanged;

不会创造一个新的、完全不同的handler对象(它不是克隆的)。这只是对相同内容的新引用PropertyChanged对象,对吗?

我做了一些测试来了解到底发生了什么:

PropertyChangedEventHandler handler = PropertyChanged;
var message = "PropertyChanged: " + PropertyChanged.GetHashCode() + "\n";
message += "handler: " + handler.GetHashCode() + "\n";
message += "are equal (1): " + (PropertyChanged.Equals(handler)) + "\n";
message += "are equal (2): " + (PropertyChanged == handler) + "\n";

MessageBox.Show(message);

结果如下:

这证实了我的理论这两个对象确实是相同的作业只是一个NOOP. 我不明白的是,这与“线程问题”(来自评论)有什么关系?!?

还有一件事:经过一些测试(使用一个非常简单的例子),我发现PropertyChanged事件是永不为空. 为什么我们需要空检查?

在我看来,之前的方法可以简化为:

private void RaisePropertyChanged(string propertyName)
{
    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

我测试了一下(再次,在一个非常简单的例子上)并且它似乎效果很好... 有什么问题或者我没有找到的东西吗?也许我只是发现了不好的例子?

无论如何,有很多东西我不知道,因为正如我所说,我刚刚开始学习 WPF 和 MVVM,但是我想了解到底发生了什么,而不仅仅是拿一些代码然后粘贴它而不理解它为什么以及如何工作。看货物崇拜编程 http://en.wikipedia.org/wiki/Cargo_cult_programming and 魔法编程 http://en.wikipedia.org/wiki/Magic_%28programming%29.


EDIT

好的,根据答案,PropertyChanged event 可以改变验证和调用之间。更多的是,PropertyChanged event 可以为空. However,我没能做到复制这些行为...

有人可以给我一个例子,这两种说法都发生吗?这肯定有助于识别类似的情况。


如果你只做

PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

你冒这样的风险PropertyChanged将为 null 并且您将得到 null 引用异常,因此您应该在事件处理程序不为 null 之前检查。现在如果你愿意

if (PropertyChanged != null)  
    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

在多线程情况下,你面临这样的风险PropertyChanged在检查和调用之间将变为空。为了避免潜在的竞争情况,您将当前委托保留在局部变量中并检查和调用它。

var handler = PropertyChanged;
if (handler != null)
    handler(this, new PropertyChangedEventArgs(propertyName));

这是安全的,因为

代表们 http://msdn.microsoft.com/en-us/library/system.delegate(v=vs.110).aspx是不可变的;一旦创建,委托的调用列表就不会改变

所以即使PropertyChanged是要在创建新委托之间进行更改,但是handler仍然会保留您当时的调用列表

var handler = PropertyChanged;

更新:C# 6 固定语法

这个争论已经在 C# 6 中得到解决,其中有一个新的运算符来帮助处理这种程度的混乱,从 C#6 开始,所有事件处理程序都应该使用以下语法作为标准:

https://codeblog.jonskeet.uk/2015/01/30/clean-event-handlers-inspiration-with-c-6/ https://codeblog.jonskeet.uk/2015/01/30/clean-event-handlers-invocation-with-c-6/

PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MVVM INotifyPropertyChanged - 线程问题? 的相关文章

随机推荐

  • 具有 ModelIO 的混合拓扑(四路/三路)

    我正在使用 ModelIO 导入一些简单的 OBJ 资源 如下所示 let mdlAsset MDLAsset url url vertexDescriptor nil bufferAllocator nil preserveTopolog
  • Windows 上的通用 ctag

    我是 ctags 新手 在阅读了有关该程序的一些信息后 我得出的结论是 Universal ctags 是最新版本 exhuberant ctags 的后继者 并且仍在积极开发中 https ctags io https ctags io
  • JAXB 编组声明的父类与实际运行时子类

    我正在使用 JAXB 来编组一个类 该类具有声明为类 Foo 的实例变量 在运行时 该实例变量被设置为 Foo 子类的实例 比如说 FooBar 类 Foo 和 FooBar 上都有基本的 JAXB 注释 XML 输出显示正在封送 Foo
  • 设置 PHP 的默认时区

    在我的网络应用程序中 我让用户从列表中选择他们喜欢的时区 其中包含PHP 支持的所有时区 http www php net manual en timezones php 这么说吧 POST timezone 是所选时区 e g Ameri
  • 如何向 topojson 文件添加属性?

    给定一个 data tsv 文件 例如 id code name 1 AL Alabama 2 AK Alaska 4 AZ Arizona 5 AR Arkansas 6 CA California 给定一个 topojson json
  • Google 脚本中的字符串以以下开头

    我正在为我们正在进行的一些选举编写数据转换脚本 第一部分将所有名称更改为大写 这部分脚本工作正常 但是 我对脚本的第二部分有疑问 有些 ID 会有 S S123456 有些则没有 S 123456 出于我的目的 我需要所有 ID 开头都没有
  • mybatis中返回HashMap,并在spring MVC中作为ModelAttribute使用

    我想使用 spring mvc modelAttribute 在 Jsp 页面中显示类别列表 在我的 mapper xml 文件中是
  • 使用 Newtonsoft 在 C# 中通过 JSON 模式验证 JSON

    使用 JSON Schema 验证 JSON 返回值始终为 true 使用Newtonsoft进行验证和测试here https www jsonschemavalidator net 与模式和数据 它总是返回 未发现错误 JSON 根据模
  • 在字符串中使用空字符 (C++)

    我正在温习 C 偶然发现了关于字符串 字符数组和空字符的奇怪行为 0 下面的代码 include
  • 有哪些优秀的 Ruby on Rails 博客? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我 6 个月前开始学习 Rails 到目前为止我很喜欢它背后的社区 有大量的论坛和文档资源可供使用 但
  • 如果流没有返回结果,Java 8 抛出异常[重复]

    这个问题在这里已经有答案了 我很好奇是否可以在以下情况下使用 orElseThrow 或者是否有更多 Java 8 方法来执行与 1 liner 相同的操作 Collection
  • 在页面关闭之前执行 JS 函数 |重定向[重复]

    这个问题在这里已经有答案了 问题 我正在使用 ASP NET Web 表单 C 我需要在页面关闭之前执行 JS 函数 无论以何种方式关闭 作为重定向或任何其他方法 额外信息 作为一些额外的信息 该函数将是到不同页面的 HTTP POST 我
  • git pull 通过 PHP exec IIS

    这是我经历过的最难诊断的问题 我似乎无法调用 exec call git pull output 该进程挂起 并且往往会导致 IIS 一起挂起 exec call git status output works fine 这是我所做的 生成
  • 如何找到 JXA 对象上的所有方法?

    我试图列出 JXA 对象的所有方法 我尝试了几种在浏览器中使用 JavaScript 的方法 但没有一个有效 gt gt Object getOwnPropertyNames Application Finder selection 0 g
  • ProgressBar Circle 在 android L (API 21) 上显示没有进度

    我有一个圆形进度条来倒计时 它在 kitkat 和之前的版本上完美运行 但在 android L 上 无论我设置什么进度 它总是显示一个完整的圆圈 Image http youspeakschwaebisch de progressbar
  • 在 XPath 中获取以下兄弟姐妹?

    我正在努力抓住li下面的类文本基于包含某个单词的树中较高的强标记 在本例中为 restaurants p class The location where the condo is situated offers a good choice
  • 使用 dlopen() 加载时解决动态库依赖关系

    我在加载动态库时遇到了问题dlopen 我尝试加载一个库 handle dlopen libmkl intel lp64 so RTLD LAZY 此代码失败并显示以下消息dlerror opt intel composer xe 2013
  • 预填充 WebView 文本字段

    我需要预先填写文本字段UIWebView我明白javascript是解决这个问题的最好方法 不幸的是我一无所知javascript在过去的几个小时里一直在摸索 一无所获 最新的拙劣尝试 void webViewDidFinishLoad U
  • 删除的指针指向什么?

    int a nullptr NULL before C 11 a new int 1 delete a 什么是a指向现在 它是否指向nullptr或者它是否指向被删除之前所指向的地址 其他一些答案错误地表示 该值不会改变 但确实如此 删除前
  • MVVM INotifyPropertyChanged - 线程问题?

    我刚刚开始学习 MVVM 和 WPF 很抱歉提出了愚蠢的问题 我正在使用不同的教程和示例来学习 并且我遇到了这个例子 http www codeproject com Articles 165368 WPF MVVM Quick Start