Это тесно связано с Безопасно ли сигнализировать и немедленно закрывать ManualResetEvent? и может предоставить одно решение этой проблемы.
Скажем, у меня есть куча потоков, которые потенциально могут выполнять ту же работу, но только одному из них следует разрешить это делать, а другим следует подождать, пока работник завершит работу, и использовать его результат.
Поэтому я хочу, чтобы работа выполнялась только один раз.
Обновление: Позвольте мне добавить, что это не проблема инициализации, которую можно решить с помощью Lazy .net 4. Под «один раз» я имею в виду один раз за задачу , и эти задачи определяются во время выполнения. Это может быть не ясно из приведенного ниже упрощенного примера.
Немного изменив простой пример из ответа Ханса Пассанта на вышеупомянутый вопрос, я думаю, следующее было бы безопасно. (Он немного отличается от только что описанного варианта использования, но с точки зрения потоков и их отношений он эквивалентен)
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 был закрыт в первую очередь?