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

让闭包捕获的变量变volatile分享

时间:2023-04-11 12:08:43 C#

让闭包捕获的变量变volatile闭包捕获的变量如何与不同的线程交互?在下面的示例代码中,我想将totalEvents声明为volatile,但C#不允许这样做。(是的,我知道这是糟糕的代码,这只是一个例子)privatevoidWaitFor10Events(){volatileinttotalEvents=0;//错误CS0106:_someEventGenerator.SomeEvent+=(s,e)=>totalEvents++;while(totalEvents<10)Thread.Sleep(100);编辑:人们似乎忽略了我的问题。我知道我不能对局部变量使用volatile。我也知道示例代码很糟糕,可以用其他方式实现,因此我的“错误代码”免责声明。这只是为了说明。无论如何,似乎没有办法对捕获的局部变量强制执行易失性语义,所以我将以不同的方式实现它。谢谢你的回答,反正我学到了很多有用的东西。?Volatile.Write来拯救:privatevoidWaitFor10Events(){inttotalEvents=0;_someEventGenerator.SomeEvent+=(s,e)=>Volatile.Write(reftotalEvents,totalEvents+1);while(totalEvents即,在这种特殊情况下我仍然会使用Interlocked.Increment。将局部变量标记为易失性是无效的。闭包可以捕获volatile字段,下面是完全合法的:volatileinttotalEvents=0;privatevoidWaitFor10Events(){_someEventGenerator.SomeEvent+=(s,e)=>totalEvents++;...}关于volatile关键字信息,请参见此处;顺便说一句,您可以考虑使用重置事件(自动、手动)、监视器类(脉冲和等待方法)或倒计时事件让线程休眠直到事件引发,这比在事件上休眠更有效。更新从编辑到问题,获得线程安全语义的一种简单方法是使用Interlocked类。以这种方式重写您的示例(尽管如其他答案中所述,有更好的写法):privatevoidWaitFor10Events(){longtotalEvents=0;_someEventGenerator.SomeEvent+=(s,e)=>Interlocked.Increment(reftotalEvents);while(Interlocked.Read(reftotalEvents)你不能声明localsvolatile。此外,还有更好的方法来实现你的目标......改用System.Threading.CountdownEvent。它比你的poll/sleep方法更有效.using(CountdownEventcde=newCountdownEvent(10)){_someEventGenerator.SomeEvent+=(s,e)=>cde.Signal();cde.Wait();}如果事件是并行触发的,这不会不幸的是,n++不是.NET中的基元操作,因此您不能期望多个线程执行n++10次实际上将n增加10,它可以增加得更少。这是一个证明它的小程序(并且在这个过程中确保在并行使用时正确处理闭包):classProgram{staticvolatileint_outer=0;staticvoidMain(string[]args){intinner=0;动作act_outer1=()=>_outer++;//Interlocked.Increment(ref_outer);动作act_inner1=()=>inner++;//Interlocked.Increment(refinner);动作组合=(i)=>{act_outer1();act_inner1();};Console.WriteLine("Noneouter={0},inner={1}",_outer,inner);Parallel.For(0,20000000,合并);Console.WriteLine("Onceouter={0},inner={1}",_outer,inner);控制台.ReadKey();Interlocked.Increment变体按预期工作。闭包捕获的局部变量被“提升”到编译器生成的不同类中,并且在这样做时,不要放松“局部不能易变”的规则,即使局部“真的”最终成为实例字段。最好的办法是手动构造闭包类(“函数对象”)或使用一些IL操作工具,例如。ILDASM。以上就是C#学习教程:让闭包捕获的变量变成volatile全部内容分享。如果对大家有用,需要进一步了解C#学习教程,希望大家多多关注---本文收集自网络,不代表侵权,如涉及侵权,请点击有权联系管理员删除。如需转载请注明出处: