【发布时间】:2019-03-10 15:55:55
【问题描述】:
public void MyTest()
{
bool eventFinished = false;
myEventRaiser.OnEvent += delegate { doStuff(); eventFinished = true; };
myEventRaiser.RaiseEventInSeperateThread()
while(!eventFinished) Thread.Sleep(1);
Assert.That(stuff);
}
为什么 eventFinished 不能是 volatile 的,这有关系吗?
在我看来,在这种情况下,编译器或运行时可能会变得聪明,并在 while 循环中“知道”eventFinished 只能为假。特别是当您考虑将提升变量生成为类的成员并将委托生成为同一类的方法的方式时,从而剥夺了 eventFinished 曾经是局部变量这一事实的优化。
【问题讨论】:
-
在这种情况下,您的变量不是本地变量!相反,它是编译器生成的类中的一个实例变量。
-
这是语义上的区别——就代码而言,它是一个恰好被捕获的局部变量......
-
我“看到”的是一个在不同线程中更新的局部变量。即使我知道编译器会为我的局部变量创建一个实例变量,但预编译器显然不会或“太固执”而无法承认它。
-
我看不出这不是 C# 编译器错误?或者仅仅是 var 捕获的一个陷阱?无论哪种方式,这个陷阱与其他几个在 var 捕获匿名方法中不那么微妙的陷阱相结合,确实将 C# 变成了一团糟。开始时很好,但现在它与 C++ 一样糟糕/更糟(我认为考虑到这些副作用很奇怪、不直观且无用,情况会更糟)。同样,如果 MSFT 在实现这些编译器功能之前对正确设计它进行了更多思考,那么它没有理由变得如此糟糕。
-
这只是另一个例子,说明 C# 如何变得过于复杂而无法为自己所用。
标签: c# multithreading volatile