Перекрытый ввод / вывод: как разбудить поток на событии порта завершения или обычном событии?
Я хочу использовать пул потоков для запуска / отмены перекрывающихся операций чтения - используя ReadFile()
а также CancelIo()
соответственно - а также обработка любых событий порта завершения, когда завершены операции чтения.
- Любой поток может инициировать операцию чтения
- Любой поток может обработать событие завершения чтения
- Только поток, который инициировал чтение, может отменить его (это
CancelIo()
ограничение)
Я не уверен, как это реализовать. Один нормально звонит GetQueuedCompletionStatus()
ждать завершения событий порта и WaitForSingleObject()
ждать нормальных событий, но не совсем понятно, как их смешать. Если PostQueuedCompletionStatus()
позволил бы мне указать конкретную нить, чтобы проснуться, я был бы установлен. Есть идеи?
ОБНОВЛЕНИЕ: решение должно работать на Windows XP. К сожалению, это исключает использование CancelIoEx()
или же GetQueuedCompletionStatusEx()
,
1 ответ
1 и 2 просты, просто используйте порт завершения ввода-вывода.
Но, как вы обнаружили, 3 требует (до Windows V6 1) того же потока.
Если вы используете Windows >= V6, GetQueuedCompletionStatusEx
включает изменяемую опцию, которая заставит его вернуться, если в потоке выполняется APC. Так что используйте QueueUserAPC
поставить в очередь неоперабельный APC 1, когда вам нужен этот конкретный поток для выполнения какой-либо другой работы. Вам, конечно, понадобится некоторая потокобезопасная очередь, чтобы предоставить прерванному потоку инструкции о том, что отменить.
Если требуется совместимость с более ранней версией, все становится сложнее. Возможности:
Используйте параметр времени ожидания
GetQueuedCompletionStatus
] ( http://msdn.microsoft.com/library/aa364986) регулярно возвращаться для проверки отмены.Или, возможно, более практично, разделить пул потоков на две группы. Потоки, которые инициируют и отменяют IO. В остальное время эти потоки тратят на ожидание сигнала о выполнении одного из этих действий. Другая часть пула ожидает завершения ввода-вывода с
GetQueuedCompletionStatus
,
Ни один из них не так хорош, но это всегда проблема со старыми версиями: им не хватает функциональности.
1 Используйте неработающий APC вместо выполнения работы в APC, чтобы обойти ограничения на то, что можно сделать в APC, и его неотъемлемые проблемы с параллелизмом. (Поскольку APC выполняется в потоке, любые блокировки, которые удерживают поток, удерживаются в APC, любое защищенное состояние будет произвольно несовместимым.)