Поскольку OpenDevice
является асинхронным (как вы упомянули в комментарии), он работает в потоке, отличном от вызывающего. Иногда это заканчивается до того, как будет выполнена следующая строка в источнике:
OpenDevice(); // Async: may finish before the next line executes!
WaitForEvent = EventEnum.DeviceOpened;
Когда это происходит, DeviceOpenedEvent
не делает то, что вы хотите, потому что WaitForEvent
по-прежнему EventEnum.None
:
if (WaitForEvent == EventEnum.DeviceOpened)
TestAutoResetEvent.Set();
Решение состоит в том, чтобы изменить ваш код так, чтобы вы сигнализировали о завершении внутри метода, который гарантированно работает в правильном порядке. Вот простая реализация, которая удаляет перечисление и использует один дескриптор ожидания для каждого события, которое вам нужно ждать:
protected AutoResetEvent deviceOpenedEvent = new AutoResetEvent(false);
protected AutoResetEvent deviceLockedEvent = new AutoResetEvent(false);
bool TestDevice() {
OpenDevice();
// Do some unrelated parallel stuff here ... then
deviceOpenedEvent.WaitOne();
LockDevice();
deviceLockedEvent.WaitOne();
}
void DeviceOpenedEvent() {
deviceOpenedEvent.Set();
}
Еще проще, если вы контролируете OpenDevice
: просто позвоните deviceOpened.Set()
, когда все будет готово. Вы даже можете изменить OpenDevice
, чтобы принять событие автоматического сброса и построить его прямо внутри TestDevice
, что уменьшит вашу подверженность многопоточным ошибкам.