如何检查std::thread
是否仍在运行(以独立于平台的方式)?
它缺少timed_join()
方法,joinable()
不适用于此。
我想在线程中使用std::lock_guard
锁定互斥锁并使用互斥锁的try_lock()
方法来确定它是否仍然被锁定(线程正在运行),但它似乎不必要地复杂对我来说。
你知道更优雅的方法吗?
更新:要明确:我想检查线程是否干净地退出。一个'悬挂'线程被认为是为了这个目的而运行。
答案 0 :(得分:91)
如果您愿意使用C ++ 11 std::async
和std::future
来运行任务,那么您可以使用wait_for
std::future
函数来检查如果线程仍然以这样一个整洁的方式运行:
#include <future>
#include <thread>
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono_literals;
/* Run some task on new thread. The launch policy std::launch::async
makes sure that the task is run asynchronously on a new thread. */
auto future = std::async(std::launch::async, [] {
std::this_thread::sleep_for(3s);
return 8;
});
// Use wait_for() with zero milliseconds to check thread status.
auto status = future.wait_for(0ms);
// Print status.
if (status == std::future_status::ready) {
std::cout << "Thread finished" << std::endl;
} else {
std::cout << "Thread still running" << std::endl;
}
auto result = future.get(); // Get result.
}
如果您必须使用std::thread
,则可以使用std::promise
来获取未来的对象:
#include <future>
#include <thread>
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono_literals;
// Create a promise and get its future.
std::promise<bool> p;
auto future = p.get_future();
// Run some task on a new thread.
std::thread t([&p] {
std::this_thread::sleep_for(3s);
p.set_value(true); // Is done atomically.
});
// Get thread status using wait_for as before.
auto status = future.wait_for(0ms);
// Print status.
if (status == std::future_status::ready) {
std::cout << "Thread finished" << std::endl;
} else {
std::cout << "Thread still running" << std::endl;
}
t.join(); // Join thread.
}
这两个例子都将输出:
Thread still running
这当然是因为在任务完成之前检查了线程状态。
但话说回来,就像其他人已经提到的那样做起来可能更简单:
#include <thread>
#include <atomic>
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono_literals;
std::atomic<bool> done(false); // Use an atomic flag.
/* Run some task on a new thread.
Make sure to set the done flag to true when finished. */
std::thread t([&done] {
std::this_thread::sleep_for(3s);
done = true;
});
// Print status.
if (done) {
std::cout << "Thread finished" << std::endl;
} else {
std::cout << "Thread still running" << std::endl;
}
t.join(); // Join thread.
}
修改强>
还有std::packaged_task
与std::thread
一起用于更清洁的解决方案,而不是使用std::promise
:
#include <future>
#include <thread>
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono_literals;
// Create a packaged_task using some task and get its future.
std::packaged_task<void()> task([] {
std::this_thread::sleep_for(3s);
});
auto future = task.get_future();
// Run task on new thread.
std::thread t(std::move(task));
// Get thread status using wait_for as before.
auto status = future.wait_for(0ms);
// Print status.
if (status == std::future_status::ready) {
// ...
}
t.join(); // Join thread.
}
答案 1 :(得分:6)
一个简单的解决方案是使用一个布尔变量,线程在定期的时间间隔内设置为true,并且由想知道状态的线程检查并设置为false。如果变量为false,则该线程不再被视为活动状态。
更加线程安全的方法是让子线程增加一个计数器,并且主线程将计数器与存储值进行比较,如果经过太长时间后相同,那么子线程被认为是不活动的。
但是请注意,C ++ 11中没有办法实际杀死或删除已挂起的线程。
编辑如何检查线程是否已完全退出:基本上与第一段中描述的技术相同;将布尔变量初始化为false。子线程执行的最后一件事是将其设置为true。然后主线程可以检查该变量,如果为true则在子线程上进行连接而没有太多(如果有的话)阻塞。
Edit2 如果线程因异常退出,则有两个线程“主”函数:第一个函数在其中调用try
- catch
第二个“真正的”主线程功能。第一个main函数设置“have_exited”变量。像这样:
bool thread_done = false;
void *thread_function(void *arg)
{
void *res = nullptr;
try
{
res = real_thread_function(arg);
}
catch (...)
{
}
thread_done = true;
return res;
}
答案 2 :(得分:3)
这个简单的机制可用于检测线程的完成而不会在连接方法中阻塞。
std::thread thread([&thread]() {
sleep(3);
thread.detach();
});
while(thread.joinable())
sleep(1);
答案 3 :(得分:1)
创建一个正在运行的线程和调用线程都可以访问的互斥锁。当正在运行的线程启动时,它会锁定互斥锁,当它结束时,它会解锁互斥锁。要检查线程是否仍在运行,调用线程将调用mutex.try_lock()。返回值是线程的状态。 (如果try_lock有效,请确保解锁互斥锁)
这个问题的一个小问题,mutex.try_lock()将在创建线程的时间和锁定互斥锁之间返回false,但是使用稍微复杂的方法可以避免这种情况。
答案 4 :(得分:0)
肯定有一个互斥锁包变量初始化为false
,该线程设置为true
,作为它退出前的最后一件事。这是否足以满足您的需求?
答案 5 :(得分:0)
您始终可以检查线程的ID是否与默认构造的std :: thread :: id()不同。 正在运行的线程始终具有真正的关联ID。 尽量避免花哨的东西:)