我对async()函数或任何其他解决问题的方法有疑问。我发送到服务器指定类型的消息,我等待具体的 响应。 我有函数receive()等待服务器的响应。我在async()中调用了这个函数。
代码示例:
while (true) {
future_receive = std::async(std::launch::async, [&] {
receive();
});
do {
status = future_receive.wait_for(chrono::seconds(timeLimit));
if (status == std::future_status::timeout){
//if timeout, abort async() function
}
} while (status != std::future_status::ready);
}
我的问题是什么?在这种情况下,如果我得到“超时”,async()函数将工作, 会等到有什么事情发生,即使它永远不会到来,并在下一个周期再次被召唤, 并将创建新线程。怎么避免这个?
如何在“超时”过去后中止async()。也许任何其他方式没有async()来解决这个问题。我想只使用C ++的标准库?
答案 0 :(得分:2)
异步线程必须合作并检查它是否应继续工作或放弃,没有可行的方法强制它在没有合作的情况下停止。
一种方法是将receive()
调用替换为具有超时的类似调用,并在超时后让线程放弃,或者在超时后检查标志以指示是否继续。
while (true) {
std::atomic<bool> stop{false};
future_receive = std::async(std::launch::async, [&] {
while (!stop)
try_receive(std::chrono::seconds(1));
});
do {
status = future_receive.wait_for(chrono::seconds(timeLimit));
if (status == std::future_status::timeout){
stop = true;
}
} while (status != std::future_status::ready);
}
现在异步线程只会阻塞一秒钟,然后检查是否已经被告知放弃,否则它会再次尝试接收。
如果你愿意牺牲可移植性,这样的东西应该适用于在POSIX线程方面实现std::thread
的平台:
while (true) {
std::atomic<pthread_t> tid{ pthread_self() };
future_receive = std::async(std::launch::async, [&] {
tid = pthread_self();
receive();
});
do {
status = future_receive.wait_for(chrono::seconds(timeLimit));
if (status == std::future_status::timeout){
while (tid == pthread_self())
{ /* wait for async thread to update tid */ }
pthread_cancel(tid);
}
} while (status != std::future_status::ready);
}
这假设在receive()
调用中的某处有一个Pthreads取消点,因此pthread_cancel
会中断它。
(这比我想要的稍微复杂一点。为了处理异步线程在调用线程获取时尚未开始运行的情况,最初需要在原子中存储一些已知值。超时并尝试取消它。为了处理我存储调用线程的ID,然后等到它被更改后再调用pthread_cancel
。)