Перекрытый ввод / вывод: как разбудить поток на событии порта завершения или обычном событии?

Я хочу использовать пул потоков для запуска / отмены перекрывающихся операций чтения - используя ReadFile() а также CancelIo() соответственно - а также обработка любых событий порта завершения, когда завершены операции чтения.

  1. Любой поток может инициировать операцию чтения
  2. Любой поток может обработать событие завершения чтения
  3. Только поток, который инициировал чтение, может отменить его (это 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, любое защищенное состояние будет произвольно несовместимым.)

Другие вопросы по тегам