如果超时已经过去,如何中止async()

时间:2014-12-19 13:45:42

标签: c++ multithreading c++11 asynchronous c++-standard-library

我对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 ++的标准库?

1 个答案:

答案 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。)