如何检查std::thread
是否仍在运行(以独立于平台的方式)?它缺乏timed_join()
方法,joinable()
不是那个意思。
我想在线程中使用std::lock_guard
锁定互斥锁并使用互斥锁的try_lock()
方法来确定它是否仍然被锁定(线程正在运行),但对我来说似乎不必要的复杂。
你知道更优雅的方法吗?
更新:要明确:我想检查线程是否干净地退出。为此,“悬挂”线程被认为正在运行。
如果你愿意使用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.
}
一个简单的解决方案是有一个布尔变量,线程在定期的时间间隔内设置为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;
}
这种简单的机制可用于检测线程的完成而不会在join方法中阻塞。
std::thread thread([&thread]() {
sleep(3);
thread.detach();
});
while(thread.joinable())
sleep(1);
创建一个正在运行的线程和调用线程都可以访问的互斥锁。当正在运行的线程启动时,它会锁定互斥锁,当它结束时,它会解锁互斥锁。要检查线程是否仍在运行,调用线程将调用mutex.try_lock()。返回值是线程的状态。 (如果try_lock有效,请确保解锁互斥锁)
一个小问题,mutex.try_lock()将在创建线程之间和锁定互斥锁之间返回false,但是使用稍微复杂一些的方法可以避免这种情况。
当然有一个互斥量包装的变量初始化为false
,该线程设置为true
作为退出之前的最后一件事。这个原子是否足以满足您的需求?
您始终可以检查线程的id是否与std :: thread :: id()默认构造不同。正在运行的线程始终是真正的关联ID。尽量避免太多花哨的东西:)