如何解决C++线程加入后不能中止
所以我的程序中有 2 个线程在运行,我最终希望它们在调用此函数时终止:
void AutoClicker::TerminateThreads()
{
programrunning = false;
clicker.join();
hotkeyLoop.join();
terminateThread = true;
}
在调用之后,线程应该运行此代码:
while (1)
{
while (programrunning)
{
mouse_event(MOUSEEVENTF_LEFTDOWN,0);
mouse_event(MOUSEEVENTF_LEFTUP,0);
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
}
if (terminateThread) {
std::terminate();
}
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
但最后一个 if
语句似乎没有被调用。它位于我试图终止的线程内,所以它应该可以正常工作吗?我对线程很陌生,所以我真的不知道该怎么做,但这是我在网上找到的:
“当一个 std::thread
对象被销毁时,它不允许是 joinable(),即,在它被销毁之前必须发生两件事之一:
它被分离了,线程已经被破坏了,几乎无法控制它是否完成。
该线程已被join()
编辑。"
解决方法
从两件事开始:
- 不要打电话给
std::terminate()
。这不是拆除程序的好方法,并且可能会使打开的文件和其他操作系统资源挂起。此外,它适用于您的整个程序,而不仅仅是您调用它的线程。 - 如果您希望
std::thread
终止,则只需从中返回或允许它到达线程函数的末尾。
除此之外,这里有一个小程序,展示了我将如何执行您所描述的操作:
#include <iostream>
#include <atomic>
#include <chrono>
#include <thread>
void threadfunc(std::atomic<bool>& running)
{
while (running) {
std::cout << "beep\n";
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
void waitThread(std::atomic<bool>& running)
{
std::this_thread::sleep_for(std::chrono::seconds(10));
running = false;
}
int main()
{
std::atomic<bool> running = true;
std::thread t1(threadfunc,std::ref(running));
std::thread t2(waitThread,std::ref(running));
t1.join();
t2.join();
}
希望你能在这里找到一些东西来让你的程序工作。
编辑: 从 OP 对另一个答案的评论中澄清一些内容:
类似于:std::thread t1(threadfunc,std::ref(running));
创建一个执行所提供函数的活动线程。一旦该函数停止(返回),线程就会处于僵死状态,即不执行但仍处于活动状态并持有资源。
https://en.cppreference.com/w/cpp/thread/thread/joinable
一个线程已经执行完代码,但还没有加入 仍然被认为是一个活动的执行线程,因此 可以加入。
为了将线程从僵尸状态中拉出并清理其资源,您必须对其调用 join()
。请注意,您可以在该线程完成执行之前或之后在该线程上调用 join()
- 如果您在之前加入,则会阻塞直到加入的线程完成,如果您在之后加入,则拖延的线程将被清除并立即继续。
或者,您可以在线程上调用 detach()
:
https://en.cppreference.com/w/cpp/thread/thread/detach
将执行线程与线程对象分离,允许 继续独立执行。任何分配的资源都将 线程退出后释放。
但是一旦你分离了一个线程,你就不能再加入它,并且在仍有活动但分离的线程运行时让你的主线程退出会以一种不太好的方式杀死分离的线程。所以只有当你确定分离的线程会在主线程之前完成时才这样做。
,您并没有真正拥有这里的所有代码,但我猜点击器线程中的方法可能看起来像
void clickerThreadFunction()
{
while(programrunning)
{
// do stuff
}
if (terminateThread)
{
std::terminate();
}
}
如果是这样,那么看代码
programrunning = false;
clicker.join();
第一行将导致点击器线程中的 while
循环退出。 clicker
方法的其余部分将运行,包括 if (terminateThread)
检查,这将失败,因为您尚未将 terminateThread
设置为 true。只有这样,一旦我们到达 clickerThreadFunction
的底部,clicker.join()
才会返回,因为 std::thread::join
等待线程完成然后返回控制权。
无论如何,我不清楚你在这里想做什么。 std::terminate
的目的是立即使程序崩溃。如果您希望这种情况发生,则不清楚您为什么要费心加入线程,因为无论如何您都不会到达该部分。
你知道join
是做什么的吗? join
等待线程完成。
您的 TerminateThreads
函数将 programrunning 设置为 false,然后等待线程完成,然后将 terminateThread 设置为 true。
线程一直运行直到 terminateThread 变为 true,所以当 TerminateThreads 函数被调用时,它永远不会到达将 terminateThread 设置为 true 的部分,因为它正在等待线程完成。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。