C++如何在if语句内启动后台线程且不阻塞主函数后续循环执行
问题原因分析
核心问题集中在两点:
join()方法本身的作用是阻塞当前线程,直到目标线程执行完毕再继续往下走,但你的MatchChecker是死循环永远不会退出,所以主线程会永远卡在checker.join()这一行,不可能进入第二个主循环。- 你把
std::thread checker定义在if语句的局部作用域里,出了if块后这个对象就被自动销毁了,自然没办法在后续的第二个循环里访问。
实现方案
这里提供两种常用的实现方式,可根据你的实际需求选择:
方案1:后台分离线程(无需后续管理线程生命周期)
如果你不需要主动控制MatchChecker线程的停止,也不需要获取它的返回结果,可以直接调用detach()将线程和线程对象分离,线程会在后台独立运行,主线程不会被阻塞。
修正后的代码示例:
#include <thread> #include <chrono> void MatchChecker() { while (1) { if (g_pOBJ->checkInMatch() == 2) { std::cout << "In Match! " << std::endl; } // 建议加休眠,避免空跑占满CPU std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } void mainFunc() { while (1) { if (checkIngame() == true) { std::thread checker(MatchChecker); // 分离线程,后台独立运行,不会阻塞主线程 checker.detach(); break; } } while (1) { std::cout << "Im doing some stuff here in this main loop" << std::endl; // 你的其他主逻辑 std::this_thread::sleep_for(std::chrono::milliseconds(100)); } }
注意:用
detach的前提是MatchChecker里用到的全局变量/外部资源(比如g_pOBJ)的生命周期要比线程长,避免线程访问到已经销毁的资源导致崩溃。
方案2:持有线程对象,后续统一管理(更安全,支持主动停止)
如果你后续需要主动停止MatchChecker线程,或者要保证程序退出前线程正常结束,建议把线程对象的定义提升到外层作用域,避免作用域失效问题。同时建议给MatchChecker加退出标志,不要用死循环。
修正后的代码示例:
#include <thread> #include <chrono> #include <atomic> // 原子退出标志,天然线程安全 std::atomic<bool> g_matchCheckerRunning = false; void MatchChecker() { g_matchCheckerRunning = true; while (g_matchCheckerRunning) { if (g_pOBJ->checkInMatch() == 2) { std::cout << "In Match! " << std::endl; } std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } void mainFunc() { // 线程对象定义在mainFunc作用域,后续可以正常访问 std::thread checker; while (1) { if (checkIngame() == true) { // 启动线程 checker = std::thread(MatchChecker); break; } } while (1) { std::cout << "Im doing some stuff here in this main loop" << std::endl; // 你的其他主逻辑 // 程序要退出的时候,主动停止线程再join if (needExit()) { g_matchCheckerRunning = false; if (checker.joinable()) { checker.join(); } break; } std::this_thread::sleep_for(std::chrono::milliseconds(100)); } }
这个方案更安全,不会出现线程访问悬空资源的问题,也能保证程序退出时线程正常清理资源。
额外注意事项
- 所有死循环的线程都建议加适当的休眠,避免CPU占用率跑满
- 只要是
std::thread对象,销毁前必须保证已经调用过join()或者detach(),否则程序会直接崩溃 - 多线程访问共享资源(比如
g_pOBJ)的时候要注意加锁,避免数据竞争问题 - 你原有代码第二个循环里的
someOtherThread.join()如果也是等待一个死循环线程的话,同样会导致阻塞,建议也按照上面的逻辑,放到程序退出的分支里再调用
内容的提问来源于stack exchange,提问作者Oday Haj Yehia
相关产品推荐
相关产品推荐

