Очередизация асинхронных вызовов процедур

Очередизация асинхронных вызовов процедур

Один поток (главный) помещает АРС в очередь целевого потока с помощью функции QueueUserAPC: 

DWORD QueueUserAPC(PAPCFUNC pfnAPC, HANDLE hThread, DWORD dwData)

hThread — дескриптор целевого потока. dwData — аргумент, который будет передан функции АРС при ее выполнении и может являться кодом завершения или сообщать функции иную информацию.

В основной функции программы ThreeStageCancel.с (сравните с программой 10.5) вызовы TerminateThread заменяются вызовами QueueUserAPC следующим образом:

// TerminateThread(transmitter_th, 0) ; заменить на АРС

// TerminateThread(receiver_th, 0); заменить на АРС

tstatus = QueueUserAPC(ShutDownTransmitter, transmitter_th, 1);

if (tstatus == 0) ReportError(…);

tstatus = QueueUserAPC(ShutDownReceiver, receiver_th, 2);

if (tstatus == 0) ReportError (…);

Функция QueueUserAPC в случае успешного ее завершения возвращает ненулевое значение, иначе — нуль. В то же время, функция GetLastError () не возвращает никакого полезного значения, и поэтому при вызове функции ReportError не требуется задавать текст сообщения об ошибке (значением последнего аргумента является FALSE).

pfnAPC — указатель на фактическую функцию, вызываемую целевым потоком, как показывает следующий фрагмент, взятый из программы ThreeStageCancel. с:

/* АРС для завершения выполнения потребителя. */

void WINAPI ShutDownReceiver(DWORD n) {

 printf("Внутри ShutDownReceiver. %d ", n);

 /* Освободить все ресурсы (в данном примере отсутствуют). */

 return;

}

Функция ShutDownTransmitter аналогична вышеприведенной, отличаясь от нее только текстом сообщения. Сразу трудно понять, каким образом эта функция, которая, казалось бы, не выполняет никаких существенных операций, может инициировать прекращение выполнения целевого принимающего потока. Соответствующие пояснения приводятся далее в этой главе.