There's no getting around the fact that you need to know what you're interrupting, and that the code has to be designed to be interrupted.
In the particular example you've chosen, replace the sleep with a timed wait on an event. You can then interrupt it by setting the event.
If you're making a synchronous I/O call, you can use CancelSynchronousIo
but of course the code handling the I/O then has to properly handle the cancellation.
If you're in an alertable wait you can queue an APC to the thread.
If you're in a message loop you can post a message or have the loop use MsgWaitForMultipleObjectsEx
.
Additional: demo code showing demonstrating how to wake SleepEx
#include <Windows.h>
#include <stdio.h>
#include <tchar.h>
HANDLE mainthread;
VOID CALLBACK DummyAPCProc(
_In_ ULONG_PTR dwParam
)
{
printf("User APC\n");
return;
}
void SleepIntr()
{
printf("Entering sleep...\n");
SleepEx(10000, TRUE);
printf("Sleep done...\n");
}
static BOOL WINAPI ctrl_handler(DWORD dwCtrlType) {
printf("ctrl_handler pressed\n");
// Wake program up!
if (!QueueUserAPC(DummyAPCProc, mainthread, NULL))
{
printf("QueueUserAPC: %u\n", GetLastError());
return TRUE;
}
return TRUE;
}
int _tmain(int argc, _TCHAR* argv[])
{
if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &mainthread, GENERIC_ALL, FALSE, 0))
{
printf("DuplicateHandle: %u\n", GetLastError());
return 0;
}
SetConsoleCtrlHandler(ctrl_handler, TRUE);
SleepIntr();
printf("awake!\n");
return 0;
}