I'm trying to use QueueUserAPC
to run some function asyncronously on a specific thread. My code is working ok when compiled for x64, but when I compile and run for x86, I get an access violation.
At the end of my post is a minimal, complete example that shows what I am trying to do (cleanup of thread and events omitted for brevity).
On my machine, when I compile and run for "x64", I get the expected output:
waiting...
async function!
waiting...
async function!
waiting...
ConsoleApplication3.exe (process 17100) exited with code 0.
When I compile and run for "x86", I get:
waiting...
async function!
And then the access violation, here:
if (WaitForSingleObjectEx(param, INFINITE, TRUE) == WAIT_OBJECT_0)
Exception thrown at 0x776227FB (ntdll.dll) in ConsoleApplication3.exe: 0xC0000005: Access violation reading location 0x36623194.
What am I doing wrong?
Full example:
#include "pch.h"
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <conio.h>
DWORD ThreadFunction(LPVOID param)
{
while (true)
{
printf("waiting...\n");
if (WaitForSingleObjectEx(param, INFINITE, TRUE) == WAIT_OBJECT_0)
break;
}
ExitThread(0);
return 0;
}
void AsyncFunction(UINT_PTR param)
{
printf("async function!\n");
}
int main()
{
HANDLE hThread, hStopEvent;
DWORD threadID;
hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ThreadFunction, hStopEvent, 0, &threadID);
Sleep(1000);
QueueUserAPC((PAPCFUNC) AsyncFunction, hThread, NULL);
Sleep(1000);
QueueUserAPC((PAPCFUNC) AsyncFunction, hThread, NULL);
Sleep(1000);
SetEvent(hStopEvent);
WaitForSingleObject(hThread, INFINITE);
}
There are two mistakes with my AsyncFunction
definition:
1 - The parameter type should be ULONG_PTR
, not UINT_PTR
. This was actually a copy-paste error from my real implementation
2 - Missing calling convention from the function
void AsyncFunction(UINT_PTR param)
should be void CALLBACK AsyncFunction(ULONG_PTR param)
And then there is no need for the cast to PAPCFUNC
here:
QueueUserAPC((PAPCFUNC) AsyncFunction, hThread, NULL);
User contributions licensed under CC BY-SA 3.0