【发布时间】:2019-07-04 08:51:34
【问题描述】:
我想要的是调用一个方法 foo() 超时(比如 1 分钟)。如果其执行时间少于 1 分钟,则返回结果。否则会抛出异常。代码如下:
//PRINT "START" IN THE LOG
auto m = std::make_shared<std::mutex>();
auto cv = std::make_shared<std::condition_variable>();
auto ready = std::make_shared<bool>(false);
auto response = std::make_shared<TResponse>();
auto exception = std::make_shared<FooException>();
exception->Code = ErrorCode::None;
std::thread([=]
{
std::unique_lock<std::mutex> lk(*m);
cv->wait(lk, [=]{ return *ready; });
try
{
//PRINT "PROCESS" IN THE LOG
auto r = foo();
*response = std::move(r);
}
catch(const FooException& e)
{
*exception = std::move(e);
}
lk.unlock();
cv->notify_one();
}).detach();
std::unique_lock<std::mutex> lk(*m);
*ready = true;
cv->notify_one();
auto status = cv->wait_for(lk, std::chrono::seconds(60));
if (status == std::cv_status::timeout)
{
//PRINT "TIMEOUT" IN THE LOG
//throw timeout exception
}
else
{
//PRINT "FINISH" IN THE LOG
if (exception->Code == ErrorCode::None)
{
return *response;
}
else
{
throw *exception;
}
}
您可以看到我在代码中添加了日志START/PROCESS/FINISH/TIMEOUT,每次执行此方法时,我都可以在日志中看到START/PROCESS/FINISH 或START/PROCESS/TIMEOUT 模式。但是,有时日志是 START/PROCESS,没有任何 FINISH/TIMEOUT。我认为cv->wait_for 应该最多阻塞当前线程 60 秒,然后它存在 TIMEOUT 或 FINISH。
foo() 方法包含对网络驱动器的磁盘 IO 操作,有时会挂起超过 1 小时(原因与此问题无关,现在无法解决),我尝试替换 foo使用线程睡眠,一切都按预期工作。这段代码有什么问题,我该如何改进?
【问题讨论】:
-
你不能选择使用信号吗?例如。 developer.gnome.org/gtkmm-tutorial/stable/sec-timeouts.html.en。还是 boost::signals ?
-
整个事情都是可疑的,因为你不能杀死一个线程。一些失控的线程将使您的系统停止运行。