C++如何实现函数定时执行而不阻塞主线程导致应用冻结
解决方案
你可以根据你的场景选择以下两种实现方案,都不会阻塞主线程导致应用冻结:
方案1:主线程时间戳校验(无额外线程开销,实现最简单)
原理是在每帧逻辑里仅判断时间差,达到5秒间隔才执行进程检测,全程没有休眠逻辑,不会阻塞主线程运行。
实现代码:
首先定义全局/静态时间记录变量:
// 记录上次执行检测的时间戳,单位毫秒 static uint64_t last_process_check = 0; // 检测间隔固定为5秒 const uint64_t CHECK_INTERVAL_MS = 5000;
修改每帧调用处的逻辑:
// 你原本每帧执行的函数 void your_frame_update_func() { // 先判断是否到了检测时间 uint64_t now = GetTickCount64(); if (now - last_process_check >= CHECK_INTERVAL_MS) { // 仅间隔到了才执行检测逻辑 bool is_debugger_exist = find1("目标调试程序进程名.exe"); if (is_debugger_exist) { // 你的关闭调试程序逻辑 } // 更新上次检测时间 last_process_check = now; } // 原有的其他帧逻辑照常执行,无任何阻塞 }
方案优势:
- 无需修改原有的
find1检测函数 - 无多线程同步开销,实现逻辑简单
- 完全不会阻塞主线程,不会出现界面冻结
方案2:独立后台线程(适合检测逻辑后续有扩展的场景)
开单独的后台线程执行检测逻辑,休眠操作仅作用于后台线程,完全不影响主线程运行。
实现代码:
#include <thread> #include <atomic> // 线程运行标记,程序退出时设为false即可结束检测线程 std::atomic<bool> g_check_thread_running = true; // 后台检测线程执行函数 void process_check_worker() { while (g_check_thread_running) { bool is_debugger_exist = find1("目标调试程序进程名.exe"); if (is_debugger_exist) { // 你的关闭调试程序逻辑 // 注意:如果此处需要操作主线程资源/UI,必须通过消息通知/加锁同步处理,避免线程安全问题 } // 后台线程休眠5秒,不影响主线程 Sleep(5000); } } // 程序启动时调用一次,启动后台检测线程 std::thread g_check_thread(process_check_worker); // 程序退出时调用,等待线程正常结束 void stop_check_thread() { g_check_thread_running = false; if (g_check_thread.joinable()) { g_check_thread.join(); } }
原有代码Bug修复
你当前的find1函数存在两个问题,建议同步修改:
- 找到目标进程直接返回,没有关闭snapshot句柄,会造成句柄泄漏
- 漏掉了Process32First返回的第一个进程的判断,会出现漏检
修复后的代码:
bool find1(const char* name) { PROCESSENTRY32 entry; entry.dwSize = sizeof(PROCESSENTRY32); auto snapshot = LI_FN(CreateToolhelp32Snapshot).safe()(TH32CS_SNAPPROCESS, NULL); bool found = false; if (LI_FN(Process32First).safe()(snapshot, &entry) == TRUE) { // 先判断第一个进程 if (strstr(entry.szExeFile, name)) { found = true; } else { while (LI_FN(Process32Next).safe()(snapshot, &entry) == TRUE) { if (strstr(entry.szExeFile, name)) { found = true; break; } } } } // 统一关闭句柄,避免泄漏 LI_FN(CloseHandle).safe()(snapshot); return found; }
内容的提问来源于stack exchange,提问作者Skeyoter
相关产品推荐
相关产品推荐

