これは、ManualResetEvent を通知してすぐに閉じても安全ですか? と密接に関連しています。その問題に対する 1 つの解決策を提供する可能性があります。
同じ作業を実行したい可能性のあるスレッドがたくさんあるとしますが、それを実行できるのは 1 つだけで、他のスレッドはワーカーが完了するまで待機してその結果を使用する必要があります。
だから、基本的には一度だけ仕事をしたいのですか?
更新: これは、.net 4 の Lazy<T> を使用して対処できる初期化の問題ではないことを付け加えておきます。1 回とは、 task ごとに 1回という意味で、これらのタスクは実行時に決定されます。これは、以下の単純化された例からは明らかではないかもしれません。
前述の質問に対する 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");
}
私の質問の核心は次のとおりだと思います。
ObjectDisposedException が原因で中止された WaitOne の呼び出しは、メモリ バリアに関して、WaitOne の呼び出しが成功したことと同等ですか?
これにより、他のスレッドによる変数workResultへの安全なアクセスが保証されます。
私の推測: それは安全でなければなりません。そうでなければ、そもそも ManualResetEvent オブジェクトが閉じられたことを WaitOne が安全に判断するにはどうすればよいでしょうか?