如何检查std::async任务是否已完成?

25

在我的图形应用程序中,我希望在另一个线程中生成一批网格。因此,我使用 std::async 异步调用成员函数。

task = async(launch::async, &Class::Meshing, this, Data(...));

在我的更新循环中,我尝试检查线程是否就绪。如果是,我将发送网格到视频卡并启动下一个线程。否则,我将跳过这些操作。

#include <future>
using namespace std;

class Class
{
public:
    void Update()
    {
        if(task.finished()) // this method does not exist
        {
            Data data = task.get();
            // ...
            task = async(launch::async, &Class::Meshing, this, Data(/* ... */));
        }
    }

private:
    struct Data
    {
        // ...
    };
    future<Data> task;
    Data Meshing(Data data)
    {
        // ...
    }
};
我该如何检查异步线程是否已经完成而不会在更新函数中卡住?

2
我认为最接近的近似方法是使用std::future::wait_for,并使用您可以管理的最小持续时间。 - GManNickG
5
看起来标准的“future”类没有继承Boost的“future”类的“is_ready”成员函数,这很遗憾... - K-ballo
1
我非常推荐观看这个视频,其中Herb Sutter讲解了异步未来的现状、它们的局限性以及一些可能克服它们的方法。视频链接:http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012-Herb-Sutter-Concurrency-and-Parallelism - Sean Cline
@K-ballo: 还有 when_anywhen_all - ronag
1
@ronag:你让我想了一秒钟,好像我们已经有了那些...是的,我们缺少“then”及其衍生词。 - K-ballo
显示剩余2条评论
1个回答

23

使用future::wait_for()。您可以指定超时时间,之后获取状态码。

示例:

task.wait_for(std::chrono::seconds(1));

这将返回 future_status::ready, future_status::deferredfuture_status::timeout,以便您了解操作的状态。您还可以指定超时时间为0,以使检查尽快返回。


3
这是最接近的,等待 _0 秒_,但并不保证它不会阻塞... - K-ballo
9
继续阅读... "由于调度或资源争用延迟,此函数可能会阻塞的时间超过 timeout_duration。" - K-ballo
4
是的 - 我看过那个。但这仅仅意味着它可能会阻塞比您设置的超时时间更长一些。所以如果操作需要2分钟,而您设置了500毫秒的超时时间,它将早于2分钟返回。因此,如果您有许多线程,操作系统的调度程序可能不会立即切换回您,这可能会导致略长一些的超时时间。但它不会一直阻塞到异步操作结束。 - lethal-guitar
4
重点是即使指定等待0秒,它可能会阻塞。它可能不像你在答案中所说的那样立即返回。如果你只想知道future是否准备好,你需要避免阻塞和上下文/线程切换。 - K-ballo
5
测试未来是否准备好本质上是对共享状态进行操作,因此需要获取共享状态内部的锁,这可能会被阻塞。也就是说,标准中的措辞并不意味着除了显而易见的成本之外还有其他成本,并且您无法获得比 wait_for 更好的结果。 - David Rodríguez - dribeas
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接