使用std :: async准备好结果后立即显示

时间:2019-06-20 10:57:58

标签: c++ asynchronous

我正在尝试发现C ++中的异步编程。这是我一直在使用的玩具示例:

#include <iostream>
#include <future>
#include <vector>

#include <chrono>
#include <thread>

#include <random>

// For simplicity
using namespace std;

int called_from_async(int m, int n)
{
    this_thread::sleep_for(chrono::milliseconds(rand() % 1000));
    return m * n;
}

void test()
{
    int m = 12;
    int n = 42;

    vector<future<int>> results;

    for(int i = 0; i < 10; i++)
    {
        for(int j = 0; j < 10; j++)
        {
            results.push_back(async(launch::async, called_from_async, i, j));
        }
    }

    for(auto& f : results)
    {
        cout << f.get() << endl;
    }
}

现在,该示例并不是很有趣,但是它提出了一个对我来说很有趣的问题。假设我要在结果“到达”时显示结果(由于延迟是随机的,所以我不知道首先要准备什么),我应该怎么做?

我在这里所做的事情显然是错误的,因为我按照创建它们的顺序等待所有任务-因此,我会等待第一个任务完成,即使它比其他任务更长。

我考虑了以下想法:对于每个future,在短时间内使用wait_for,如果准备就绪,则显示值。但是我这样做很奇怪:

while (any_of(results.begin(), results.end(), [](const future<int>& f){
    return f.wait_for(chrono::seconds(0)) != future_status::ready;
}))
{
    cout << "Loop" << endl;
    for(auto& f : results)
    {
        auto result = f.wait_for(std::chrono::milliseconds(20));
        if (result == future_status::ready)
            cout << f.get() << endl;
    }
}

这带来了另一个问题:我们会在某些get上多次致电future,这是非法的:

  

在抛出'std :: future_error'实例后调用终止
what():std :: future_error:无关联状态

所以我真的不知道该怎么办,请提出建议!

1 个答案:

答案 0 :(得分:4)

使用valid()跳过您已经呼叫过get()的期货。

bool all_ready;
do {
    all_ready = true;
    for(auto& f : results) {
        if (f.valid()) {
            auto result = f.wait_for(std::chrono::milliseconds(20));
            if (result == future_status::ready) {
                cout << f.get() << endl;
            }
            else {
                all_ready = false;
            }
        }
    }
}
while (!all_ready);