我想运行一个函数并判断函数是否在n毫秒后没有完成,停止该函数并启动另一个函数。类似这样的代码:
void run()
{
//do something that doesn't have while(1)
}
void main()
{
run();
if(runFunctionDidntFinishInSeconds(10)
{
endPrintFunction();
backupPlan();
}
return 0;
}
我搜索了一下,发现了boost :: timed_join函数。这是我的代码:
void run()
{
int a;
for (int i = 0; i < 2000; i++)
cout << i << endl;
}
int main()
{
boost::thread t = new boost::thread(&run);
if (t.timed_join(boost::posix_time::microseconds(10000))){
cout << "done" << endl;
}
else{
cout << endl << "not done" << endl;
}
system("pause");
return 0;
}
但它不会阻止线程't'运行。我去了终止线程,但这不是一个好选择。 我想要'a'函数来完成我告诉它的确切时间。 系统每16ms输入一次,我想对其进行处理,并说如果处理时间超过13ms,请离开并进行备份计划。我希望它从编写处理方法的人那里抽象出来。因此,在它的顶部放置一个while循环会让我感到延迟。 我该怎么办? 至少我认为我需要的是能够重置处理线程以执行它需要再做的事情!
答案 0 :(得分:2)
我认为你正在寻找像std :: future。
这样的东西http://en.cppreference.com/w/cpp/thread/future/wait_for
您可以在另一个线程中启动该函数,并等待该函数返回或超时。
对于你的例子:
std::future< void > future = std::async( std::launch::async, print );
auto status = future.wait_for( std::chrono::seconds( 10 ) );
if ( status == std::future_status::deferred )
{
std::cout << "deferred\n";
}
else if ( status == std::future_status::timeout )
{
std::cout << "timeout\n";
}
else if ( status == std::future_status::ready )
{
std::cout << "ready!\n";
}
然而,这并不会导致分离的线程结束。为此,必须在启动时包含一个标志,因此分离的线程可以自行清理并保存。
void run(const std::atomic_bool& cancelled)
{
int a;
for (int i = 0; i < 2000; i++)
{
cout << i << endl;
if (cancelled)
return;
}
}
std::atomic_bool cancellation_token = false;
std::future< void > future = std::async( std::launch::async,
run,
std::ref(cancellation_token) );
auto status = future.wait_for( std::chrono::seconds( 10 ) );
if ( status == std::future_status::deferred )
{
std::cout << "deferred\n";
}
else if ( status == std::future_status::timeout )
{
std::cout << "timeout\n";
cancellation_token = true;
}
else if ( status == std::future_status::ready )
{
std::cout << "ready!\n";
}
答案 1 :(得分:1)
我希望从编写处理方法的人那里抽象出来。
标准C ++没有办法从该函数的调用图外部强行中断函数的控制流(它调用的函数可以抛出,但有人不能为它们抛出)
特定于操作系统的线程系统有终止线程的方法。但是,这会使程序可能处于未定义状态,因为尚未调用任何堆栈变量的析构函数。因为当你杀死它时你不知道它在那个处理中的位置,你就无法在它之后有效地清理它。即使是C程序也不能保证可以终止任意函数;它必须是一个不动态分配内存或其他必须清理的资源的。
您可以通过非常仔细地编写您的功能来弥补这一点。但这需要编写该功能的人非常小心地编码。因此,没有抽象,因为编写函数的人必须知道规则是什么,并且需要遵循它们。
所以唯一有效的解决方案需要合作。该函数必须以这样的方式编写,即可以通过那些依赖于操作系统的功能安全地停止,或者必须编写该函数以定期检查某个值并停止本身。
答案 2 :(得分:0)
以下是两种和3/4种方法。
第一个要求您要停止的代码合作。它可以在运行时轮询某个变量,也可以定期调用一个函数,该函数可以抛出异常来暂停执行。 boost
可中断的线程遵循第二个模型。
第二个要求您启动新进程,将数据编组到函数中,然后使用IPC获取信息。如果函数没有及时返回,则会终止子进程。
第三个“半”包括用不同的语言重写代码,或者使用C ++作为脚本语言。您可以在为您执行第一个或第二个解决方案的解释器中运行代码。
现在,一个实用的替代方案(1/4解决方案)是确保该函数是纯函数的,在一个带有半可靠中止消息的单独线程中运行它(如第一个),并丢弃其返回值如果需要太长时间。这不是你想要的,但更容易。
答案 3 :(得分:0)
有一种方法可以将原子用作信号量,但是由于load
每次迭代都会发出完全内存障碍,从而降低性能:
#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
std::atomic<bool> printFinished { false };
std::atomic<bool> shouldPrintRun { true };
void print()
{
while (shouldPrintRun.load() /* && your normal stop condition*/)
{
//work..
}
printFinished.store(true);
}
int main()
{
std::thread t(print);
std::this_thread::sleep_for(std::chrono::seconds(10));
if (!printFinished.load())
{
shouldPrintRun.store(false);
t.join();
std::cout << "help!";
}
return 0;
}
如果您不希望在另一个线程上运行的函数检查是否需要停止,那么终止该线程只是 选项。
答案 4 :(得分:0)
一个可能的解决方案是,你必须将冗长的功能变成小型和小型的。短增量功能,每次从上一次调用时仍然可以继续执行任务。可以在线程中运行的下面的代码将执行时间限制器的类似工作,并且可以随意终止。
void Process()
{
bool flag = true;
while (running)
{
std::chrono::high_resolution_clock::time_point time1 = std::chrono::high_resolution_clock::now();
std::chrono::milliseconds span(16);
while ( (std::chrono::high_resolution_clock::now() - time1 ) < span)
{
flag ? incremental_function1() : incremental_function2();
if (!running) return;
}
flag = (!flag);
}
}