我有一个简单的任务调度程序:调用一个execute方法,packaged_task返回指向我的Task的指针。当任务完成后,我喜欢显示调试数据(涉及GUI,所以我需要在主线程中这样做)。我想对此使用boost::wait_for_any,如图所示,但是j->get()有时会抛出异常boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::promise_already_satisfied> >。这给我留下了两个想法。这要么是由于复制(异常类指示的复制),但我不知道这是在哪里发生的,要么是因为已经调用了get,这是不可能的,因为未来只能在这个方法块中可见,而且我已经将它们转换为shared_futrues,因此应该可以工作。
因此,在wait_for_any部分中,如何返回指向已完成的Task实例的指针?
使用future而不是shared_future编辑。
结果,异常是在我的任务之一的execute函数中抛出的,未来将把这些异常传递到get调用中。代码本身很好(除了缺少的异常处理程序)。然而,使用Boost信号(见下面的答案)可能更好。
std::vector<boost::future<Task*>> futures;
std::vector<Task*> tasks = get_tasks();
for (Task* t : tasks) {
    typedef boost::packaged_task<Task*()> task_t;
    task_t task([t]() -> Task* {
        t->execute();
        return t;
    });
    auto fut = task.get_future();
    futures.push_back(std::move(fut));
    impl->io_service.post(boost::bind(&task_t::operator(), boost::make_shared<task_t>(std::move(task))));
}
for (Task* t : tasks) {
    auto j = boost::wait_for_any(futures.begin(), futures.end());
    Task* task = j->get();
    task->display_debug();
    futures.erase(j);
}发布于 2014-10-30 08:04:17
嗯。我在这里有点迷路了。看起来你做的事情比要求的要复杂一些(为什么不使用Boost Signals2而不是通过将来对特定的“事件”进行“轮询”呢?)你似乎没有期望他们在任何特定的顺序?)。
不管它有什么价值,这里有一个对我有用的修正版本。如果我以后有更多的时间,我可能会交换意见,看看是什么解释了差异。
看吧,住在Coliru
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/make_shared.hpp>
#include <boost/thread/future.hpp>
#include <iostream>
#include <string>
#include <set>
struct Task
{
    virtual ~Task() = default;
    virtual void execute() {}
    virtual void display_debug() { std::cout << __FUNCTION__ << static_cast<void*>(this) << "\n"; }
};
std::set<Task*> get_tasks()
{
    static std::set<Task*> data{ new Task, new Task };
    return data;
}
int main() {
    struct { boost::asio::io_service io_service; } impl_instance;
    auto impl = &impl_instance;
    std::vector<boost::shared_future<Task*>> futures;
    std::set<Task*> tasks = get_tasks();
    for (Task* t : tasks) {
        typedef boost::packaged_task<Task*> task_t;
        task_t wrap([t]() -> Task* {
            t->execute();
            return t;
        });
        auto fut = wrap.get_future();
        futures.push_back(std::move(fut));
        impl->io_service.post(boost::bind(&task_t::operator(), boost::make_shared<task_t>(std::move(wrap))));
    }
    boost::thread th([&]{ impl->io_service.run(); });
    while (!futures.empty()) {
        auto j = boost::wait_for_any(futures.begin(), futures.end());
        auto fut = *j;
        futures.erase(j);
        Task* task = fut.get();
        task->display_debug();
        // optionally:
        // tasks.erase(task);
    }
    th.join();
}https://stackoverflow.com/questions/26643909
复制相似问题