以下是我正在使用的代码的简洁示例:
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!
return TRUE;
}
int _tmain(int argc, _TCHAR* argv[])
{
SetConsoleCtrlHandler(ctrl_handler, TRUE);
SleepIntr();
printf("awake!\n");
return 0;
}
这个想法是当按下ctr + c时,应该中断睡眠并且程序应该继续执行并打印醒来!"或者至少给我一个堆栈跟踪按ctrl + c时执行的位置。
SleepEx
调用可以是任何阻塞的系统调用,例如来自套接字的阻塞读取。
我应该在我的ctrl_handler
写什么来打断电话?如果没有终止整个过程,我什么也没找到。如果不可能,那么我接受这个作为答案,但我真的想知道原因。
以下是使用nanosleep
代替SleepEx
为Linux编写的等效程序:
#include <signal.h>
#include <stdio.h>
#include <time.h>
void ctrl_c (int sid, siginfo_t *info, void *data) {
printf("Im a ctrl_c\n");
}
int main (int argc, char *argv[]) {
struct sigaction act = {0};
act.sa_sigaction = &ctrl_c;
sigaction(SIGINT, &act, NULL);
struct timespec t, t2;
t.tv_sec = 5;
t.tv_nsec = 0;
printf("sleep start\n");
nanosleep (&t, &t2);
printf("sleep end\n");
return 0;
}
它的工作原理与我想要的完全一样。 nanosleep中的Ctrl + c会立即中断它,并通过打印&#34; sleep end&#34;继续执行。为什么在Windows上为SleepEx做类似的工作?
编辑 SleepEx
的第二个参数当然应为TRUE。这是一个错字。
答案 0 :(得分:1)
您无需知道自己中断了什么,并且必须将代码设计为中断。
在您选择的特定示例中,使用定时等待事件替换睡眠。然后,您可以通过设置事件来中断它。
如果您正在进行同步I / O调用,则可以使用CancelSynchronousIo
,但当然处理I / O的代码必须正确处理取消。
如果您处于可警告的等待状态,则可以将APC排入该线程。
如果您正处于消息循环中,则可以发布消息或让循环使用MsgWaitForMultipleObjectsEx
。
附加: 演示代码,演示了如何唤醒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;
}