You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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函数存在两个问题,建议同步修改:

  1. 找到目标进程直接返回,没有关闭snapshot句柄,会造成句柄泄漏
  2. 漏掉了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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 16:27:00