这与发出信号并立即关闭 ManualResetEvent 是否安全?并可能为该问题提供一种解决方案。
假设我有一堆线程可能想要做同样的工作,但应该只允许一个线程去做,其他的应该等到工作人员完成并使用它的结果。
所以基本上我希望工作只完成一次。
更新: 让我补充一点,这不是可以使用 .net 4 的 Lazy<T> 解决的初始化问题。一次我的意思是每个任务一次,这些任务是在运行时确定的。从下面的简化示例中可能不清楚这一点。
稍微修改一下 Hans Passant 对上述问题的回答中的简单示例,我想以下是安全的。(与刚才描述的用例略有不同,但就线程及其关系而言,是等价的)
static void Main(string[] args)
{
ManualResetEvent flag = new ManualResetEvent(false);
object workResult = null;
for (int ix = 0; ix < 10; ++ix)
{
ThreadPool.QueueUserWorkItem(s =>
{
try
{
flag.WaitOne();
Console.WriteLine("Work Item Executed: {0}", workResult);
}
catch (ObjectDisposedException)
{
Console.WriteLine("Finished before WaitOne: {0}", workResult);
}
});
}
Thread.Sleep(1000);
workResult = "asdf";
flag.Set();
flag.Close();
Console.WriteLine("Finished");
}
我想我的问题的核心是:
就内存屏障而言,对 WaitOne 的调用是否因 ObjectDisposedException 而中止,是否等同于对 WaitOne 的成功调用?
这应该确保其他线程对变量workResult的安全访问。
我的猜测:它必须是安全的,否则 WaitOne 怎么能安全地确定 ManualResetEvent 对象首先被关闭了?