Sam*_*eff 6 .net c# multithreading dispose
今天我们惊讶地发现线程正在等待ManualResetEvent继续等待事件,即使它已经关闭.我们原本以为调用Close()会隐含地发出等待线程的信号.
我们跟踪这个问题是因为我们的一些Windows服务并没有像我们想的那样快速关闭.我们正在改变所有Dispose关闭ManualResetEvent对调用的引用的实现Set.
任何人都可以解释为什么Close不暗中打电话Set?你什么时候想要一个等待的线程继续等待?
这是我们的测试代码,用于演示我们的发现:
private static readonly Stopwatch _timer = Stopwatch.StartNew();
public static void Test()
{
var sync = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(state =>
{
Log("ThreadPool enter, waiting 250ms...");
sync.WaitOne(250);
Log("ThreadPool exit");
});
Log("Main sleeping 100");
Thread.Sleep(100);
Log("Main about to close");
// sync.Set(); // Is Set called implicitly? No...
sync.Close();
Log("Main waiting for exit 500ms");
Thread.Sleep(500);
}
private static void Log(string text)
{
Console.WriteLine("{0:0} {1}", _timer.ElapsedMilliseconds, text);
}
Run Code Online (Sandbox Code Playgroud)
当我们通过Set注释的调用运行此代码时,我们得到了这个..
0 Main sleeping 100
0 ThreadPool enter, waiting 250ms...
103 Main about to close
103 Main waiting for exit 500ms
259 ThreadPool exit
Run Code Online (Sandbox Code Playgroud)
当我们明确打电话时,Set我们得到这个
0 Main sleeping 100
0 ThreadPool enter, waiting 250ms...
98 Main about to close
98 ThreadPool exit
98 Main waiting for exit 500ms
Run Code Online (Sandbox Code Playgroud)
Close是一种处理对象的方法(Close并且Dispose在此类上产生相同的行为)。它不影响句柄的状态。假设在所有情况下,用户都希望线程等待我关闭的句柄以继续似乎不合理。事实上,句柄正在使用的事实应该表明您不应该Close首先调用。
这不是一个“为什么不应该Set隐式调用?”的问题,这是一个概念问题:如果你调用Close,你不应该再关心该对象。使用Set和Reset来控制线程之间的执行流程;不要对任何对象(包括对象)调用Close(或) ,直到不再使用它们为止。DisposeWaitHandle