在Win32 C 中,如何同時WaitForSingleObject和檢測Ctrl-C?
我通過在 Windows 的 Code::Blocks C 編譯器中編譯它來嘗試以下控制臺應用程式。
然后,我嘗試在運行時多次按下 Control-C...當主執行緒處于“WaitForSingleObject”時,它基本上不會呼叫 control-c 處理程式。
有沒有辦法解決這個問題?
最終,我希望我的 Control-C 處理程式使用 TerminateThread 殺死輔助執行緒并將控制權回傳給破壞 WaitForSingleObject 的主執行緒......但是,由于等待第二個執行緒被寫入,我無法更改任何代碼......
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <atomic>
using namespace std;
BOOL WINAPI fun1(DWORD id);
DWORD WINAPI fun2(void*);
atomic<DWORD> threadid {0};
int main()
{
DWORD threadid1;
cout << "Hello world!" << endl;
SetConsoleCtrlHandler(fun1, TRUE);
HANDLE H1 = CreateThread(NULL, 0, fun2, 0, 0, &threadid1);
threadid = threadid1;
WaitForSingleObject(H1, INFINITE);
return 0;
}
BOOL WINAPI fun1(DWORD id)
{
Beep(750, 300);
printf("CtrlHandler:(%ld)\n", id);
if (threadid != 0) {
HANDLE H2 = OpenThread(THREAD_TERMINATE, FALSE, threadid);
if (H2) {
//TerminateThread(H2, 0);
//threadid = 0;
CloseHandle(H2);
}
}
return TRUE;
}
DWORD WINAPI fun2(void*)
{
// This thread will eventually do some work...
// and I don't want to rewrite this code...
// to check for a flag from another thread...
int count = 0;
while(1) {
printf("count: %d\n", count);
Sleep(1000);
}
return 0;
}
uj5u.com熱心網友回復:
一個SetConsoleCtrlHandler()處理程式得到通過在自己的執行緒作業系統運行。這在檔案中說明如下:
https://docs.microsoft.com/en-us/windows/console/handlerroutine
與函式一起使用的應用程式定義的
SetConsoleCtrlHandler函式。控制臺行程使用此函式來處理行程接收到的控制信號。當接收到信號時,系統會在行程中創建一個新執行緒來執行該函式。
您需要讓該信號執行緒通知您的作業執行緒自行終止,您不能(安全地)直接終止執行緒(即,不要使用TerminateThread())。
試試這個:
#include <windows.h>
#include <cstdio>
#include <iostream>
#include <atomic>
using namespace std;
BOOL WINAPI fun1(DWORD);
DWORD WINAPI fun2(void*);
atomic<bool> exitThread {false};
int main()
{
cout << "Hello world!" << endl;
SetConsoleCtrlHandler(fun1, TRUE);
HANDLE H1 = CreateThread(NULL, 0, fun2, 0, 0, NULL);
if (H1)
{
WaitForSingleObject(H1, INFINITE);
CloseHandle(H1);
}
return 0;
}
BOOL WINAPI fun1(DWORD id)
{
Beep(750, 300);
printf("CtrlHandler:(%lu)\n", id);
exitThread = true;
return TRUE;
}
DWORD WINAPI fun2(void*)
{
// This thread will eventually do some work...
int count = 0;
while (!static_cast<bool>(exitThread)) {
printf("count: %d\n", count );
Sleep(1000);
}
return 0;
}
但是,請注意創建一個執行緒只是為了等待它是浪費執行緒。你也可以main()直接做你的作業,例如:
#include <windows.h>
#include <cstdio>
#include <iostream>
#include <atomic>
using namespace std;
BOOL WINAPI fun1(DWORD);
atomic<bool> exitApp {false};
int main()
{
cout << "Hello world!" << endl;
SetConsoleCtrlHandler(fun1, TRUE);
// This will eventually do some work...
int count = 0;
while (!static_cast<bool>(exitApp)) {
printf("count: %d\n", count );
Sleep(1000);
}
return 0;
}
BOOL WINAPI fun1(DWORD id)
{
Beep(750, 300);
printf("CtrlHandler:(%lu)\n", id);
exitApp = true;
return TRUE;
}
uj5u.com熱心網友回復:
我稍微清理了您的代碼,看起來 Ctrl C 處理程式正在按預期運行(即使它沒有做任何特別有用的事情)。當我輸入 Ctrl C 時,我看到fun1可以在主執行緒運行時多次運行WaitForSingleObject。
您的原始代碼fun1在列印前發出嗶嗶聲,并且沒有重繪 stdout緩沖區,所以您可能認為代碼實際上沒有運行或被延遲了。
請注意,我只是在回答您提出的有關在等待物件時檢測 Ctrl C 的問題;我不是要幫助您在 Ctrl C 處理程式中做任何有用的事情。
這是我用于測驗的代碼的清理版本:
#include <windows.h>
#include <stdio.h>
#include <atomic>
std::atomic<DWORD> threadid {0};
BOOL WINAPI fun1(DWORD id) {
printf("fun1: %ld\n", id);
fflush(stdout);
Beep(750, 100);
// This doesn't do anything useful; can be removed.
if (threadid != 0) {
HANDLE H2 = OpenThread(THREAD_TERMINATE, FALSE, threadid);
if (H2) { CloseHandle(H2); }
}
return 1;
}
DWORD WINAPI fun2(void *) {
unsigned int count = 0;
while(1) {
count ;
printf("count: %d\n", count);
fflush(stdout);
Sleep(4000);
}
return 0;
}
int main() {
printf("Hello world!\n");
fflush(stdout);
SetConsoleCtrlHandler(fun1, TRUE);
DWORD threadid1;
HANDLE H1 = CreateThread(NULL, 0, fun2, 0, 0, &threadid1);
threadid = threadid1;
printf("Waiting for single oblect.\n");
fflush(stdout);
WaitForSingleObject(H1, INFINITE);
printf("Done waiting for single oblect.\n");
fflush(stdout);
return 0;
}
示例輸出:
Hello world!
Waiting for single oblect.
count: 1
count: 2
fun1: 0
fun1: 0
fun1: 0
fun1: 0
fun1: 0
fun1: 0
fun1: 0
fun1: 0
fun1: 0
count: 3
count: 4
我在 MSYS2 中編譯了代碼,針對 64 位 Windows,使用以下命令:
g -std=gnu 20 -Wall -Wextra test.cpp
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/386829.html
