Не совсем понятно, о чем вы здесь спрашиваете, но я попробую.
То, сводит ли ожидание APC к нулю преимущества асинхронного ввода-вывода, полностью зависит от вашей конструкции. Если вы написали что-то вроде:
WriteFileEx(..., &overlapped, CompleteWrite);
SleepEx(INFINITE, TRUE);
Тогда ясно, что вы ничего не сделали, кроме чрезмерного усложнения вашей программы. Вы могли бы также сделать синхронный ввод / вывод.
Но вы также можете написать что-то вроде:
while (work_to_do)
{
DoSomeWork();
WriteFileEx(results);
SleepEx(0, TRUE);
}
Теперь вы избежали простоев. Если для завершения WriteFileEx требуется много времени, поток может продолжить работу в промежуточный период.
Вы также можете создать поток, который обслуживает запросы. Что-то вроде:
DWORD ThreadProc(...)
{
while (!done)
{
SleepEx(INFINITE, TRUE);
}
}
Этот поток просто сидит и ждет, пока кто-нибудь отправит ему команду, используя QueueUserAPC
. Если такой поток выполняет ввод / вывод, он может захотеть сделать это асинхронно, чтобы позволить ему обрабатывать другие команды в ожидании завершения ввода / вывода. (С другой стороны, чтобы избежать проблем с повторным входом, он может не хотеть это сделать.)
Надеюсь, это дает некоторое представление о том, как эти функции предназначались для использования. Но имейте в виду, что это очень старые технологии. Вы бы редко, если вообще использовали их в современной программе. Вместо этого используйте такие функции, как CreateThreadPoolIo
/ StartThreadPoolIo
, чтобы Windows запустила завершение ввода-вывода в выделенном для вас рабочем потоке. Или еще лучше: используйте высокоуровневую библиотеку, ориентированную на задачи, и избегайте этих низкоуровневых деталей.
РЕДАКТИРОВАТЬ - Выполнение операций ввода-вывода в потоке главного окна
Краткий ответ на эту проблему: не делай этого. Запустите ваш ввод-вывод в рабочем потоке и отправьте результаты обратно в основной поток, используя PostMessage
или SendMessage
. Если по какой-то причине вы не можете этого сделать, вы должны использовать измененный цикл обработки сообщений. Вместо GetMessage
используйте MsgWaitForMultipleObjects
, что позволит вам обрабатывать оконные сообщения в ожидании завершения ввода-вывода.
// error checking omitted
OVERLAPPED overlapped{};
ReadFile(file_handle, buffer, bytes_to_read, &bytes_read, &overlapped);
while (true)
{
DWORD wait_result = MsgWaitForMultipleObjects(
1,
&file_handle,
FALSE,
INFINITE,
QS_ALLINPUT);
if (wait_result = WAIT_OBJECT_0)
{
// I/O completed...
break;
}
}