ФункцияWaitNamedPipe
позволяет клиентскому приложению канала синхронно ожидать доступного соединения на сервере именованного канала. Затем вы вызываетеCreateFile
, чтобы открыть канал в качестве клиента. Псевдокод:
// loop works around race condition with WaitNamedPipe and CreateFile
HANDLE hPipe;
while (true) {
if (WaitNamedPipe says connection is ready) {
hPipe = CreateFile(...);
if (hPipe ok or last error is NOT pipe busy) {
break; // hPipe is valid or last error is set
}
} else {
break; // WaitNamedPipe failed
}
}
Проблема в том, что все это блокирующие синхронные вызовы. Каков хороший способ сделать это асинхронно? Например, я не могу найти API, который использует перекрывающийся ввод-вывод для этого.Например, для каналов серверовфункцияConnectNamedPipe
предоставляет параметры lpOverlapped
, позволяющие серверу асинхронно ожидать клиента. Затем сервер канала может вызвать WaitForMultipleObjectsи дождаться завершения операции ввода-вывода или любого другого события, которое будет сигнализировано (например, событие, сигнализирующее потоку об отмене ожидающего ввода-вывода и завершении).
Единственный способ, который я могу придумать, это вызвать WaitNamedPipe
в цикле с коротким конечным временем ожидания и проверить другие сигналы, если время ожидания истекло. В качестве альтернативы, в вызове цикла CreateFile
, проверьте другие сигналы, а затем вызовите Sleep
с небольшой задержкой (или WaitNamedPipe
). Например:
HANDLE hPipe;
while (true) {
hPipe = CreateFile(...);
if (hPipe not valid and pipe is busy) {
// sleep 100 milliseconds; alternatively, call WaitNamedPipe with timeout
Sleep(100);
// TODO: check other signals here to see if we should abort I/O
} else
break;
}
Но этот метод, на мой взгляд, вонючий. Если канал недоступен в течение некоторого времени, поток продолжает работать — загружая ЦП, потребляя энергию, требуя, чтобы страницы памяти оставались в ОЗУ и т. д. На мой взгляд, поток, который полагается на Sleep
или короткие тайм-ауты плохо работают и являются признаком неаккуратного многопоточного программирования.
Но какая в этом случае альтернатива?