Pat*_*nga 17 c# multithreading volatile
public void MyTest()
{
bool eventFinished = false;
myEventRaiser.OnEvent += delegate { doStuff(); eventFinished = true; };
myEventRaiser.RaiseEventInSeperateThread()
while(!eventFinished) Thread.Sleep(1);
Assert.That(stuff);
}
Run Code Online (Sandbox Code Playgroud)
为什么eventFinished不能变得不稳定并且重要吗?
在我看来,在这种情况下,编译器或运行时可能会变得聪明,并且在while循环中"知道"eventFinished只能为false.特别是当您考虑提升变量作为类的成员生成的方式以及委托作为同一类的方法时,从而剥夺了eventFinished曾经是局部变量这一事实的优化.
Nol*_*rin 12
存在一个线程原语,ManualResetEvent准确地执行此任务 - 您不希望使用布尔标志.
这样的事情应该做的工作:
public void MyTest()
{
var doneEvent = new ManualResetEvent(false);
myEventRaiser.OnEvent += delegate { doStuff(); doneEvent.Set(); };
myEventRaiser.RaiseEventInSeparateThread();
doneEvent.WaitOne();
Assert.That(stuff);
}
Run Code Online (Sandbox Code Playgroud)
关于缺乏volatile对局部变量关键字的支持,我认为没有任何理由可以在C#中理论上不可能这样做.最有可能的是,它不受支持仅仅因为在C#2.0之前没有使用这样的功能.现在,由于存在匿名方法和lambda函数,这种支持可能会变得有用.如果我在这里遗漏了什么,请有人澄清问题.
Mar*_*ell 10
在大多数情况下,局部变量特定于线程,因此与之相关的问题volatile完全没有必要.
当像在你的例子中,它是一个"捕获"变量时,当它被静默地实现为编译器生成的类上的字段时,这会发生变化.所以理论上它可能是不稳定的,但在大多数情况下,它不值得额外的复杂性.
特别是,像Monitor(aka lock)Pulse等的东西也可以这样做,就像任何数量的其他线程结构一样.
线程很棘手,主动循环很少是管理它的最佳方式......
重新编辑... secondThread.Join()将是显而易见的事情 - 但如果您真的想使用单独的令牌,请参阅下文.这样做的好处(比较之类ManualResetEvent)是它不需要操作系统中的任何东西 - 它完全在CLI内部处理.
using System;
using System.Threading;
static class Program {
static void WriteLine(string message) {
Console.WriteLine(Thread.CurrentThread.Name + ": " + message);
}
static void Main() {
Thread.CurrentThread.Name = "Main";
object syncLock = new object();
Thread thread = new Thread(DoStuff);
thread.Name = "DoStuff";
lock (syncLock) {
WriteLine("starting second thread");
thread.Start(syncLock);
Monitor.Wait(syncLock);
}
WriteLine("exiting");
}
static void DoStuff(object lockHandle) {
WriteLine("entered");
for (int i = 0; i < 10; i++) {
Thread.Sleep(500);
WriteLine("working...");
}
lock (lockHandle) {
Monitor.Pulse(lockHandle);
}
WriteLine("exiting");
}
}
Run Code Online (Sandbox Code Playgroud)
如果要使局部变量表现为易失性,也可以使用Voltile.Write.如:
public void MyTest()
{
bool eventFinished = false;
myEventRaiser.OnEvent += delegate { doStuff(); Volatile.Write(ref eventFinished, true); };
myEventRaiser.RaiseEventInSeperateThread()
while(!Volatile.Read(eventFinished)) Thread.Sleep(1);
Assert.That(stuff);
}
Run Code Online (Sandbox Code Playgroud)