Dan*_*ett -1 .net c# while-loop
编辑几年:在我开始使用C#/ .NET时,这显然是一种可怕的方法.希望这个问题有助于另一个具有相同"问题"的菜鸟.
这是处理这种情况的最佳方式吗?
while(true)
{
if(Main.ActiveForm != null)
{
Main.ActiveForm.Invoke(new MethodInvoker(Main.SomeMethod));
break;
}
}
Run Code Online (Sandbox Code Playgroud)
这是在第二个线程上执行的.
Eri*_*ert 37
这是处理这种情况的最佳方式吗?
只是为了澄清,场景是"我有一个引用类型的属性;一旦属性不为null我希望调用它的一个方法",并且该技术是"旋转另一个线程,忙 - 等到值不是null,调用,并停止等待".
您的问题的答案是否定的,这不是解决此问题的最佳方法.由于几个原因,这是解决这个问题的可怕方法.
首先,代码完全错误.C#语言不保证此代码有效.如果它工作,那么它是偶然的,它可以随时停止工作.
这段代码有三个原因是错误的.
它错误的第一个原因是因为线程在现代操作系统上的工作方式.两个线程可能都分配给它们自己的处理器.当处理器访问现代机器上的内存时,它不会每次都出现在主内存中.相反,它会在您第一次点击地址时将数百或数千个附近值提取到缓存中.从那时起,它访问本地缓存而不是将昂贵的公交车返回主存.其含义应该是显而易见的:如果一个线程正在写入而另一个线程正在读取,那么一个线程可能正在写入一个处理器缓存而另一个线程可能正在从完全不同的处理器缓存中读取.如果没有强制它们保持一致,它们可以永远不一致,因此即使在另一个线程上设置了属性,你的循环也可以永远运行.
(并且"向后"的情况也是可能的;如果属性的值现在为 null,并且在过去的某个时间设置,那么第二个线程可能正在读取旧的,陈旧的值而不是新鲜的因此,它可以决定不等待,并在属性的陈旧值上调用该方法.)
这段代码错误的第二个原因是因为它有竞争条件.假设某人在第一个线程上将该属性赋值为非null,然后线程二将其读取为非null,因此您输入"if"的主体,然后线程三将其分配回null,然后线程二读取它as null和崩溃.
这个代码错误的第三个原因是因为编译器(C#编译器或抖动)被允许"优化"它以使它永远保持循环而不再进行第二次测试.允许优化器分析代码,并意识到在第一次循环之后,如果测试失败,那么循环的其余部分都不会导致它成功.然后允许在下次跳过测试,因为它"知道"它不能成功.请记住,优化器可以进行任何在单线程程序中不可见的优化.
优化器实际上并没有进行这种优化(据我所知)但是它被允许,未来版本可以这样做.优化器可以并且确实在类似情况下进行类似的优化.
为了使这个代码正确,必须有一个内存屏障.引入障碍的最常见技术是使访问"易变".内存屏障迫使处理器放弃其缓存并返回主内存,并阻止编译器进行积极的优化.当然,属性可能不易变,并且这种技术完全破坏了性能,因为它消除了现代处理器中最重要的优化之一.您也可以通过运营商鸽子访问主内存,与点击缓存相比,成本太高了.
其次,代码很糟糕,因为你正在通过紧密循环检查属性来烧掉整个处理器.想象一下处理器是一辆汽车.也许你的企业拥有四辆车.你正带着其中一个并且高速地不停地绕着街区行驶,直到邮递员到达.这是浪费宝贵的资源!这将使整个机器的响应性降低,在笔记本电脑上,它会像没有明天一样通过电池咀嚼,它会产生废热,这很糟糕.
但是我注意到,至少你是将跨线程调用编组回UI线程,这是正确的.
解决这个问题的最好方法是不解决它.如果在属性变为非null时需要执行某些操作,则最佳解决方案是处理与该属性关联的更改事件.
如果你不能这样做那么最好的解决方案是让行动成为财产的责任.更改setter,以便在设置为非null时执行操作.
如果您无法将其作为财产的责任,则由设置该财产的用户负责.要求每次将属性设置为非null时,都要执行该操作.
如果你不能这样做那么解决这个问题的最安全的方法是不要启动另一个线程.相反,启动一个定时器,每隔半秒左右发出一次主线程信号,让定时器事件处理程序执行检查并执行操作.
忙碌等待几乎总是错误的解决方案.
Ser*_*rvy 10
您需要做的就是将事件处理程序附加到Activated表单事件.在该表单的构造函数中添加以下内容:
Activated += SomeMethod;
Run Code Online (Sandbox Code Playgroud)
在以前使用其他应用程序之后重新激活表单时,它将被触发.
这种方法的主要优点是,您可以避免创建一个新线程,只是让它坐在一个spinwait(使用大量的CPU周期).
| 归档时间: |
|
| 查看次数: |
4779 次 |
| 最近记录: |