Eri*_*bes 3 .net multithreading synchronization waithandle
我继承了一些线程代码,在查看它之后,我发现了这样的结构(在后台线程方法中):
private ManualResetEvent stopEvent = new ManualResetEvent(false);
private void Run_Thread() {
while (!stopEvent.WaitOne(0, true)) {
// code here
}
}
Run Code Online (Sandbox Code Playgroud)
通常有公共或私人Stop()方法,如下所示:
public void Stop() {
stopEvent.Set();
bgThread.Join();
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:在这里使用等待句柄可以提供什么?似乎这样做是为了确保停止的信号是原子操作,但我认为写入布尔值无论如何都是原子的.如果是这种情况,是否有任何理由不使用以下内容:
private void Run_Thread() {
while(!stop) {
// code here
}
}
public void Stop() {
stop = true;
bgThread.Join();
}
Run Code Online (Sandbox Code Playgroud)
写入bool变量确实是原子的,但除非变量也是易失性的(或者你引入了一些其他的同步),否则它可能从其他线程中看不到.这些问题很难追查和重现.
例如,在我的x64笔记本电脑上,以下程序正确停止.在我的x86上网本上,它永远挂起.(两者都编译csc /o+ Test.cs).
using System;
using System.Threading;
class Test
{
static bool stop = false;
static void Main(string[] args)
{
new Thread(CountLots).Start();
Thread.Sleep(100);
stop = true;
Console.WriteLine("Finished...");
}
static void CountLots()
{
long total = 0;
while (!stop)
{
total++;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这种特殊情况下,使用volatile标志似乎是合理的 - 尽管如果你使用.NET 4,最好使用Task取消机制:)
当然,通常使用除标志之外的其他东西的更好的理由是,如果你想要等待一些条件 - 无论是"是否有新项目"或"我被取消"(或两者) - 没有紧密循环.