当前位置: 首页 > 编程语言 > C#

C#学习教程:.net4.5中的事件提升和阅读介绍Share

时间:2023-04-10 14:39:17 C#

.net4.5中的事件提升和阅读介绍阅读简介正如我刚才所解释的,编译器有时会将多个读取融合为一个。编译器还可以将单个读取拆分为多个读取。在.NETFramework4.5中,读取引入远不如读取消除常见,并且仅在非常罕见的特定情况下才会发生。然而,它有时会发生。publicclassReadIntro{privateObject_obj=newObject();voidPrintObj(){对象obj=_obj;if(obj!=null){Console.WriteLine(obj.ToString());//可能抛出NullReferenceException}}voidUninitialize(){_obj=null;如果检查PrintObj方法,obj.ToString表达式中的obj值似乎永远不会为null。但是,该行代码实际上可能会抛出NullReferenceException。CLRJIT可能会像这样编写PrintObj方法一样对其进行编译:voidPrintObj(){if(_obj!=null){Console.WriteLine(_obj.ToString());但那不是一个与事件模式一起工作的吗?!voidRaiseEvent(){varmyEvent=MyEvent;if(myEvent!=null){myEvent(this,EventArgs.Empty);我错过了什么重要的东西吗?这篇文章让我感到困惑,我做了一些研究。我发现了两种思想流派。有人说这种模式是安全的,因为CLR2.0内存模型比1.x更严格,禁止使用。“ReadsandWritesCannotBeIntroduced”,MSDN杂志(10月5日),文章了解低锁技术在多线程应用程序中的影响。“.NET内存模型禁止它[阅读简介]引用GC堆内存的普通变量”,JoeDuffy,Windows上的并发编程,pp517-8。[注意:JoeDuffy基本上说了同样的话,但保留了在堆栈上引入读取的可能性,这不是共享的,因此是安全的]我发现那些“.NET2.0内存模型”的解释很奇怪。我已经阅读了2012ECMACLI规范,以及C#标准,没有发现禁止阅读介绍的声明。它们不太可能削弱2.0和4之间的内存模型。(??)另一方面,我相信JIT团队知道这些模式并且不会破坏它们,至少在x86上是这样……但是说是与标准中所说的不同。团队决策可能会在未来或在其他平台上发生变化。编辑不要错过下面EricLippert的评论:“未读介绍”是MicrosoftCLI实现的承诺。ECMA标准中没有任何内容,当使用其他实现(如Mono)时,所有的赌注都没有了。结束编辑有人说这不安全具体来说:你引用的文章中的IgorOstrovsky,以及这篇博文的评论中的StephenToub的讨论:http://blogs.msdn.com/b/pfxteam/archive/2013/01/13/合作暂停异步方法.aspx。基本上他们说读取引入或消除是一种常见的编译器优化,如果C#和JIT不更改单线程行为,则允许它们这样做。[注意:EricLippert曾说过C#编译器目前不执行此类优化。]请注意,Igor似乎意识到JIT非常保守,并在文章中明确指出您的示例代码不会在x86-x64上的.NET4.5中中断。另一方面,他说,如果它是更复杂的代码模式、未来或过去的.net版本或其他平台,它可能会在其他情况下崩溃。解决方案如果要100%安全,解决方案是使用volatilereads。C#标准将易失性读取和写入定义为副作用,因此不能引入或删除它们。ECMACLI标准有一个类似的明确声明,volatile读写不会被删除。关于线程安全事件的注释正如许多人指出的那样,线程安全不仅仅是引发事件的代码。您的事件处理程序应该准备好在取消订阅后被调用。我同意HansPassant的观点,最好的指导是“不要这样做”,但有时您需要这样做。在这些情况下,请确保您的事件处理程序代码也是线程安全的。在这些情况下,您可能还需要考虑更简单的基于锁的同步方法。以上就是《C#学习教程:.net4.5事件推广阅读介绍》的全部内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场,如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处: