为啥 Sleep() 函数会阻止整个循环工作?
Posted
技术标签:
【中文标题】为啥 Sleep() 函数会阻止整个循环工作?【英文标题】:Why does the Sleep() function prevent the entire loop from working?为什么 Sleep() 函数会阻止整个循环工作? 【发布时间】:2021-08-12 14:43:29 【问题描述】:我们的目标是创建一个记录击键并将其写入文本文件的程序。目前,只需轻按一个键就会写入该键一百次,所以我试图放慢速度。
但是,使用 Sleep()
将阻止整个代码执行任何操作,除非我使用 Sleep(0)
(据我了解,这意味着“不要让较低优先级的线程运行”)。
代码:
// Subconsole is Windows so the running app is not visible to a certain someone
int __stdcall WinMain(_In_ HINSTANCE hinstance, _In_opt_ HINSTANCE hprevinstance, _In_ LPSTR lpcmdline, _In_ int ncmdshow)
FILE* write;
char running = 1;
fopen_s(&write, "typelog.txt", "w");
while (running)
_Bool keytoggle;
char key;
// Go from A to Z and see if the key for that was pressed
for (int i = 0x41; i < 0x5A; i++)
// Is the highest order bit for GetAsyncKeyState a 1 (is the key down)
keytoggle = (GetAsyncKeyState(i) & (1 << 15)) != 0;
if (keytoggle)
key = i; // save the key that was pressed
break;
// If the key was pressed, write it, otherwise write a space
if (keytoggle)
if (write)
fprintf(write, "%c", key);
else
if (write)
fprintf(write, " ");
// Sleep for like, just one millisecond please
Sleep(1);
return 0;
听说使用Sleep
,即使是1ms,由于系统定时器的原因,也可以延长到20ms。是这样吗?就算是,为什么代码根本不执行?
我搜索了一个小时左右,一无所获。如果你能帮忙就太好了。
【问题讨论】:
为此存在WH_KEYBOARD_LL
Sleep(0)
的意思是“我可以放弃我的时间片并让上下文切换到其他进程”。 为什么你使用 Sleep()?如果你不能回答这个问题,那么不要使用 Sleep()。
@AsafItach: Sleep
不是 sleep
。
使用MsgWaitForMultipleObjects
等待键盘上读取的内容,然后使用ReadConsoleInput
了解发生了什么。
当然,如果您不介意在按下某个键之前阻止您的程序,请仅使用ReadConsoleInput
,这与 getch() 非常相似,但会返回更详细的信息(向上键、向下键、ctrl , shift, alt, 不同的小键盘值, 功能键,...)。
【参考方案1】:
通过调试,问题是您的 txt 句柄在调用 Sleep(1)
时没有关闭。您可以使用Message-Only Windows 和Raw Input 来实现您的目标。例如:
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, nullptr, hInstance, nullptr);
if (!hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
RawInput(hWnd);
return TRUE;
和
#define BUFFER 512
HRESULT ShowRawInputInfo(LPARAM lParam)
UINT dwSize = 0;
HRESULT hResult;
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
LPBYTE lpb = new BYTE[dwSize];
if (lpb == NULL)
return 0;
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize)
OutputDebugString(TEXT("GetRawInputData does not return correct size !\n"));
RAWINPUT* raw = (RAWINPUT*)lpb;
WCHAR szTempOutput[BUFFER];
if (raw->header.dwType == RIM_TYPEKEYBOARD)
hResult = StringCchPrintf(szTempOutput, BUFFER,
TEXT(" Kbd: make=%04x Flags:%04x Reserved:%04x ExtraInformation:%08x, msg=%04x VK=%04x \n"),
raw->data.keyboard.MakeCode,
raw->data.keyboard.Flags,
raw->data.keyboard.Reserved,
raw->data.keyboard.ExtraInformation,
raw->data.keyboard.Message,
raw->data.keyboard.VKey);
if (FAILED(hResult))
// TODO: write error handler
OutputDebugString(szTempOutput);
else if (raw->header.dwType == RIM_TYPEMOUSE)
hResult = StringCchPrintf(szTempOutput, BUFFER,
TEXT("Mouse: usFlags=%04x ulButtons=%04x usButtonFlags=%04x usButtonData=%04x ulRawButtons=%04x lLastX=%04x lLastY=%04x ulExtraInformation=%04x\r\n"),
raw->data.mouse.usFlags,
raw->data.mouse.ulButtons,
raw->data.mouse.usButtonFlags,
raw->data.mouse.usButtonData,
raw->data.mouse.ulRawButtons,
raw->data.mouse.lLastX,
raw->data.mouse.lLastY,
raw->data.mouse.ulExtraInformation);
if (FAILED(hResult))
// TODO: write error handler
OutputDebugString(szTempOutput);
delete[] lpb;
return 0;
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
DWORD dwStyleOfStaticText = 0;
HWND hBmp2 = NULL;
WORD reason = 0;
switch (message)
case WM_INPUT:
ShowRawInputInfo(lParam);
break;
case WM_KEYDOWN:
WCHAR szTempOutput[512];
StringCchPrintf(szTempOutput, 512,
TEXT(" KeyValue=%04x\n"), wParam);
OutputDebugString(szTempOutput);
//PostMessage(hWnd, WM_COMMAND, KILLTHEWIN, 0);// hope it serializes message
//PostQuitMessage(0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
return 0;
编辑:或挂钩
【讨论】:
谢谢,我忘了Sleep()
会干扰已经写入文件的数据。由于您的解决方案使用了一个窗口(我已经避免使用)和几个我不熟悉的功能,所以我现在的基本解决方案是每次写入文件时打开和关闭文件。谢谢。以上是关于为啥 Sleep() 函数会阻止整个循环工作?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Django-Summernote 会阻止 prepopulated_fields 工作?
Python 3:超过 100 个索引的列表在索引 47 之后循环。为啥?我该如何阻止这个?
为啥 Spring SAML 会阻止 Spring OAuth2 工作?
PHP:为啥用括号括起来的函数调用会阻止“通过引用”通知? [复制]