【问题标题】:Signalling the completion of std::async task发出 std::async 任务完成的信号
【发布时间】:2016-04-15 20:11:18
【问题描述】:

我使用std::async 来加快任务的执行速度,该任务以前是按顺序执行的。

我的实现如下:

  1. 启动预先配置的任务数量(例如最多 10 个并发任务)
  2. 这些任务的未来存储在一个向量中。
  3. 一旦一个任务完成,它就会启动另一个任务,因此在任何时间点,最多有 10 个任务(此值已配置)正在运行。
  4. 在启动 10 个任务后,我的实现通过调用 get() 来等待最旧的任务(即向量中的第一个任务)完成。

虽然这可以正常工作,但有可能 10 个任务中的任何一个都可以先完成。我的实现总是等待向量中的第一个任务。有没有办法知道 10 项任务中的哪一项先完成?

例如未来对象本身发出信号,表明它已准备就绪。

我想实现类似于本文中提到的“WhenAny()”函数的功能:https://msdn.microsoft.com/en-us/library/jj155756.aspx

【问题讨论】:

  • 显示一些代码。有很多方法可以做到这一点。
  • 感谢您的回答。我会在问题中添加更多细节。
  • 例如,您可以在完成时手动进行回调。如果“下一个任务函数”需要仅在最初创建任务的函数范围内可用的信息,则可以将回调编写为 lambda。
  • 回调是否有任何原因无法启动下一个任务本身?那会更简单。当然,可能还有一些我不知道的额外限制来阻止它。

标签: c++ c++11 asynchronous c++14


【解决方案1】:

我认为等效于 WhenAny (C#) 的功能尚未纳入 C++11/14 标准,认为它被视为未来的实验性扩展(请参阅this)。 我认为 Boost 库的最新版本包括 when_any,请查看this。 这个company 还出售一个包含when_any 的完整线程库。

【讨论】:

    【解决方案2】:

    给他们每个人一个 ID 并使用一个原子来存储第一个完成的。

    在所有功能范围内的某个地方:

    std::atomic<int> first_id(0);
    

    每项任务完成时:

    first_id.compare_exchange_strong(0, id);
    

    其中id 是从 1 到 10。它只会运行一次,第一个运行它将替换 0。

    编辑:以上是您的字面问题的答案。但它并不能真正帮助你做你想做的事。为了做你想做的事,我会将向量更改为一个队列,并让每个任务在它退出时进入下一个队列(在修改它之前你还需要一个锁来锁定队列。)或者,你可以使用线程池。 (无耻插件:here's mine。)线程池可以让您将所有任务排入队列,但只使用n 线程,这将防止调度程序负担过重,同时仍使编码变得简单。

    【讨论】:

      【解决方案3】:

      使用线程池。将所有任务排队。让他们在完成后向原子计数器报告,并在计数器说一切都完成时让他们向条件变量发出信号。

      堆栈溢出和其他地方的线程池实现比比皆是。

      我发现直接在客户端代码中使用 C++11 线程原语是有问题的;使用它们来编写小助手是一个更好的主意。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-03-28
        • 1970-01-01
        • 2015-08-01
        • 2015-11-30
        • 1970-01-01
        • 1970-01-01
        • 2016-08-22
        相关资源
        最近更新 更多