Я чувствую, что должен знать ответ на этот вопрос, но я все равно спрошу, если я сделаю потенциально катастрофическую ошибку.
Следующий код выполняется, как ожидалось, без ошибок/исключений:
static void Main(string[] args)
{
ManualResetEvent flag = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(s =>
{
flag.WaitOne();
Console.WriteLine("Work Item 1 Executed");
});
ThreadPool.QueueUserWorkItem(s =>
{
flag.WaitOne();
Console.WriteLine("Work Item 2 Executed");
});
Thread.Sleep(1000);
flag.Set();
flag.Close();
Console.WriteLine("Finished");
}
Конечно, как обычно бывает с многопоточным кодом, успешный тест не доказывает, что это фактически потокобезопасный. Тест также завершится успешно, если я положил Close
до Set
, хотя в документации четко указано, что попытка сделать что-либо после Close
приведет к поведению undefined.
Мой вопрос в том, что когда я вызываю метод ManualResetEvent.Set
, гарантирован ли он сигнализировать все ожидания потоков, прежде чем возвращать управление вызывающему абоненту? Другими словами, если предположить, что я могу гарантировать, что дальнейших вызовов на WaitOne
не будет, безопасно ли здесь закрыть дескриптор или возможно, что в некоторых случаях этот код помешает некоторым официантам получить сигнал или результат ObjectDisposedException
?
В документации только говорится, что Set
помещает его в состояние "сигнализированное" - он, похоже, не претендует на то, что официанты действительно получат этот сигнал, поэтому я хотел бы быть уверен.