所以我有2个线程在我的程序中运行,我最终希望它们在调用这个函数时终止:
void AutoClicker::TerminateThreads()
{
programrunning = false;
clicker.join();
hotkeyLoop.join();
terminateThread = true;
}
调用之后,线程应该运行以下代码:
while (1)
{
while (programrunning)
{
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 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
对象被销毁时,它不允许是可接合的(),也就是说,在它被销毁之前必须发生两件事之一:
它已被分离,线程已进入野外,几乎无法控制它是否已完成。
线程已被
join()
编辑。">
从两件事开始:
- 不调用
std::terminate()
。这不是一种拆除程序的好方法,可能会使打开的文件和其他操作系统资源挂起。而且,它适用于整个程序,而不仅仅是调用它的线程。 - 如果你想要一个
std::thread
终止,那么就从它返回或允许它到达线程函数的结束。
有了这些,下面是一个小程序,展示了我将如何做你所描述的事情:
#include <iostream>
#include <atomic>
#include <chrono>
#include <thread>
void threadfunc(std::atomic<bool>& running)
{
while (running) {
std::cout << "beepn";
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
将执行线程从线程对象中分离出来,允许继续独立执行。任何分配的资源都将被线程退出后释放。
但是一旦你分离了一个线程,你就不能再加入它了,当主线程退出时,仍然有活的但是分离的线程在运行,以一种不好的方式杀死了分离的线程。因此,只有当您确定分离线程将在主线程之前完成时才这样做。
这里没有所有的代码,但我猜clicker线程中的方法可能看起来像
void clickerThreadFunction()
{
while(programrunning)
{
// do stuff
}
if (terminateThread)
{
std::terminate();
}
}
如果是这种情况,那么查看代码
programrunning = false;
clicker.join();
第一行将导致clicker线程中的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的部分,因为它正在等待线程完成。