麻烦多个std :: threads和主程序执行

时间:2013-08-08 21:02:30

标签: c++ multithreading c++11 stdthread stdasync

我几天来一直在努力想出一个启动一些计时器的机制,而不是让它在主程序执行时钟。 .join().detach()wait_until()等的组合

我所拥有的是std::thread的向量,我想:

  • 执行第一个职位
  • 等待它完成
  • 执行下一个职位
  • 等待它完成

同时我的应用程序的其余部分正在运行,用户点击等等。我想出的所有内容似乎都是:

  • 阻止主程序在计时器运行时运行

  • 从主线程分离但随后定时器同时运行,我在上一个完成之后想要一个。

我甚至发布了C++11 std::threads and waiting for threads to finish,但我似乎无法解决任何问题。

我应该使用std::launch::async吗?

编辑:我不确定为什么这对我来说太难掌握。我的意思是视频游戏一直这样做。以Tiny Tower为例。你存放你的地板,这些操作中的每一个都有一个延迟,从你开始库存,直到该物品库存,它触发弹出的HUD并说,“现在放置地板”。与此同时,整个游戏都在为你做其他事情。我必须密集,因为我无法理解这一点。

2 个答案:

答案 0 :(得分:4)

这段代码将在一个单独的线程中执行std::vector个无效任务。

typedef std::vector<std::function< void() >> task_list;
typedef std::chrono::high_resolution_clock::duration timing;
typedef std::vector< timing > timing_result;

timing_result do_tasks( task_list list ) {
  timing_result retval;
  for (auto&& task: list) {
    std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
    task();
    std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
    retval.push_back( end-start );
  }
  return retval;
}
std::future<timing_result> execute_tasks_in_order_elsewhere( task_list list ) {
  return std::async( std::launch::async, do_tasks, std::move(list) );
}

这应该在主线程之外运行串行的每个任务,并返回包含时序结果的std::future

如果您希望计时结果为较小的块(即,在它们准备就绪之前),您将需要做更多的工作。我从std::packaged_task开始,然后返回std::vector<std::future< timing >>并从那里开始。

上述代码未经测试/未编译,但不应存在任何根本缺陷。

您会注意到上述内容不使用std::threadstd::thread是一个低级别的工具,您应该在其上构建工具,而不是您应该直接使用的工具(由于要求joindetach编辑,因此它非常脆弱在破坏之前,除其他外)。

虽然std::async没有什么可写回家的,但它非常适合快速和脏的多线程,你想要执行一个串行任务并在“其他地方”执行。通过std::future缺乏良好的信号使得它不是完全一般的(并且是你可能想要在std::thread附近写更高级别抽象的原因。)

这是一个将运行一系列任务的任务,它们之间的延迟最小:

#include <chrono>
#include <iostream>
#include <vector>
#include <functional>
#include <thread>
#include <future>

typedef std::chrono::high_resolution_clock::duration duration;
typedef std::chrono::high_resolution_clock::time_point time_point;
typedef std::vector<std::pair<duration, std::function< void() >>> delayed_task_list;

void do_delayed_tasks( delayed_task_list list ) {
  time_point start = std::chrono::high_resolution_clock::now();
  time_point last = start;
  for (auto&& task: list) {
    time_point next = last + task.first;
    duration wait_for = next - std::chrono::high_resolution_clock::now();
    std::this_thread::sleep_for( wait_for );
    task.second();
    last = next;
  }
}
std::future<void> execute_delayed_tasks_in_order_elsewhere( delayed_task_list list ) {
  return std::async( std::launch::async, do_delayed_tasks, std::move(list) );
}
int main() {
  delayed_task_list meh;
  meh.emplace_back( duration(), []{ std::cout << "hello world\n"; } );
  std::future<void> f = execute_delayed_tasks_in_order_elsewhere( meh );
  f.wait(); // wait for the task list to complete: you can instead store the `future`
}

这应该使助手async线程在运行每个任务之前(至少与您使用的持续时间一样)休眠。如上所述,执行每项任务所花费的时间不会计入延迟时间,因此如果任务花费的时间比延迟时间长,那么您最终将完成任务运行,并且它们之间没有任何延迟。如果你愿意,改变这应该很容易。

答案 1 :(得分:0)

你的麻烦是可以理解的,因为你需要的是为了让定时器不阻止你的事件循环,是一个事件循环,而C ++还没有标准的。您需要使用其他框架(例如Qt,Boost.Asio(?)或非可移植API(select()等))来编写事件循环。