没有(标准的)方法可以进入线程并杀死它,无论如何这通常都是一个坏主意.更清洁的选择是将开始时间和最大持续时间传递给函数,然后(可能在计算过程中多次)检查当前时间减去开始时间是否太长.
我会做这样的事情:
#include <chrono>
template <typename Clock = std::chrono::steady_clock>
class timeout
{
public:
typedef Clock clock_type;
typedef typename clock_type::time_point time_point;
typedef typename clock_type::duration duration;
explicit timeout(duration maxDuration) :
mStartTime(clock_type::now()),
mMaxDuration(maxDuration)
{}
time_point start_time() const
{
return mStartTime;
}
duration max_duration() const
{
return mMaxDuration;
}
bool is_expired() const
{
const auto endTime = clock_type::now();
return (endTime - start_time()) > max_duration();
}
static timeout infinity()
{
return timeout(duration::max());
}
private:
time_point mStartTime;
duration mMaxDuration;
};
Run Code Online (Sandbox Code Playgroud)
这个简单的实用程序跟踪开始时间和最大持续时间(并提供指定无穷大的方法),并允许用户查询简单事实,最重要的是是否发生了超时.
测试如下; 你可以通过定义/取消定义来添加假延迟FAKE_DELAY:
#include <iostream>
#include <future>
#define FAKE_DELAY
void fake_delay()
{
#ifdef FAKE_DELAY
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
#endif
}
void short_running_function(timeout<> timelimit)
{
fake_delay();
if (timelimit.is_expired())
std::cout << "short running thread ran out of time" << std::endl;
else
std::cout << "short running function finished" << std::endl;
}
void long_running_function(timeout<> timelimit)
{
for (unsigned i = 0; i < 10; ++i) {
if (timelimit.is_expired())
{
std::cout << "long running thread ran out of time" << std::endl;
return;
}
std::cout << "long running thread doing work" << std::endl;
fake_delay();
}
std::cout << "long running function finished" << std::endl;
}
int main()
{
std::async(short_running_function,
timeout<>(std::chrono::milliseconds(500))).wait();
std::async(short_running_function,
timeout<>(std::chrono::milliseconds(5000))).wait();
std::async(long_running_function,
timeout<>(std::chrono::milliseconds(500))).wait();
std::async(long_running_function,
timeout<>(std::chrono::milliseconds(5000))).wait();
std::async(long_running_function,
timeout<>::infinity()).wait();
}
Run Code Online (Sandbox Code Playgroud)
FAKE_DELAY 关闭的一个可能输出:
短期运行函数后
的短期运行函数后
长时间运行的线程执行工作的
长期运行的线程执行工作的
长期运行的线程执行工作的
长期运行的线程执行工作的
长期运行的线程执行工作的
长期运行的线程执行工作的
长期运行的线程执行工作的
长期运行的线程执行工作
长期运行线程
长期线程数工作线程
长期
长期执行
长期线程
运行
长期线程
运行线程做
长期执行线程
运行工作工作
运行线程做功
长时间运行的线程执行工作的
长期运行的线程执行工作的
长期运行的函数后
长时间运行的线程执行工作的
长期运行的线程执行工作的
长期运行的线程执行工作的
长期运行的线程执行工作的
长期运行的线程执行工作的
长期运行的线程执行工作的
长期运行的线程执行工作
长时间运行的线程执行工作
长[R unning线程做工作
长时间运行线程做工作
长时间运行功能完成
FAKE_DELAY 打开一个可能的输出:
短时间运行线程跑出时间
短运行功能完成
长时间运行线程做工作
长时间运行线程运行时间
长时间运行线程做工作
长时间运行线程做工作
长时间运行线程做工作
长时间运行线程做工作
长时间运行线程做
长时间运行线程跑出来的时候
长时间运行的线程执行工作的
长期运行的线程执行工作的
长期运行的线程执行工作的
长期运行的线程执行工作的
长期运行的线程执行工作的
长期运行的线程执行工作的
长期运行的线程执行工作的
长期运行的线程执行工作的
长期运行的线程执行工作
长时间运行的线程正在
完成工作长时间运行
该标准没有提供任何非合作杀死线程的方法.缺少自动超时功能只是另一个例子.
相反,您必须实现传递给的代码std::async来处理这种情况.协同杀死线程的一种模式是向函数传递一个对象,该对象提供检查异步函数是否应该继续的方法,如果不是,则抛出异常.
struct Time_out {
std::chrono::steady_clock start = std::chrono::steady_clock::now();
std::chrono::milliseconds timeout;
Time_out(std::chrono::milliseconds t) : timeout(t) {}
void check() {
if (start + timeout < std::chrono::steady_clock::now())
throw timeout_exception();
}
};
std::future<void> f = std::async([](Time_out t) {
while(more work) {
// do work
t.check();
}
}, Time_out(std::chrono::seconds(2));
f.get();
Run Code Online (Sandbox Code Playgroud)