Проблема с несколькими std :: threads и выполнением основной программы

В течение нескольких дней я изо всех сил пытался придумать механизм для запуска нескольких таймеров, чтобы он не отслеживал время выполнения основной программы. Сочетания .join() а также .detach(), wait_until(), так далее

То, что у меня есть, это вектор std::thread и я хочу:

  • выполнить первую позицию
  • ждать, пока это не закончится
  • выполнить следующую позицию
  • ждать, пока это не закончится

в то время как остальная часть моего приложения работает, пользователи щелкают по чему-то и т. д. Все, что я придумываю, кажется либо:

  • заблокировать запуск основной программы во время работы таймеров

или же

  • отсоединиться от основного потока, но затем таймеры запускаются одновременно, как я хочу, после завершения предыдущего.

Я даже написал: C ++ 11 std :: threads и ожидание завершения потоков но нет разрешения, которое, как мне кажется, может иметь смысл.

я должен использовать std::launch::async может быть?

РЕДАКТИРОВАТЬ: Я не уверен, почему это так трудно для меня, чтобы понять. Я имею в виду видео игры делают это все время. Возьмите крошечную башню, например. Вы заполняете свои этажи, и каждая из этих операций имеет задержку с момента, когда вы запускаете запас, до того момента, когда этот товар складывается, и он вызывает HUD, который всплывает и говорит: «Теперь пол заполнен». Между тем вся игра работает для вас, чтобы делать другие вещи. Я должен быть плотным, потому что я не могу понять это.

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::thread, std::thread это низкоуровневый инструмент, на котором вы должны создавать инструменты, а не то, что вы должны использовать напрямую (он довольно хрупкий из-за требования, что он должен быть joinред или detachред до уничтожения, между прочим).

В то время как 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 поток ожидания в течение (по крайней мере, пока) продолжительности, которую вы используете перед выполнением каждой задачи. Как написано, время, затрачиваемое на выполнение каждой задачи, не засчитывается в задержки, поэтому, если задачи занимают больше времени, чем задержка, вы получите задачи, выполняемые без задержки между ними. Изменить это должно быть легко, если вы хотите.

4

Другие решения

Ваша проблема понятна, потому что то, что вам нужно для того, чтобы иметь таймеры, которые не блокируют ваш цикл событий, — это цикл событий, а в C ++ еще нет стандартного. Вам нужно использовать другие фреймворки (например, Qt, Boost.Asio (?) Или непереносимые API (select () и т. Д.)) Для записи циклов событий.

0

По вопросам рекламы [email protected]