В течение нескольких дней я изо всех сил пытался придумать механизм для запуска нескольких таймеров, чтобы он не отслеживал время выполнения основной программы. Сочетания .join()
а также .detach()
, wait_until()
, так далее
То, что у меня есть, это вектор std::thread
и я хочу:
в то время как остальная часть моего приложения работает, пользователи щелкают по чему-то и т. д. Все, что я придумываю, кажется либо:
или же
Я даже написал: C ++ 11 std :: threads и ожидание завершения потоков но нет разрешения, которое, как мне кажется, может иметь смысл.
я должен использовать std::launch::async
может быть?
РЕДАКТИРОВАТЬ: Я не уверен, почему это так трудно для меня, чтобы понять. Я имею в виду видео игры делают это все время. Возьмите крошечную башню, например. Вы заполняете свои этажи, и каждая из этих операций имеет задержку с момента, когда вы запускаете запас, до того момента, когда этот товар складывается, и он вызывает HUD, который всплывает и говорит: «Теперь пол заполнен». Между тем вся игра работает для вас, чтобы делать другие вещи. Я должен быть плотным, потому что я не могу понять это.
Этот фрагмент кода выполнит 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
поток ожидания в течение (по крайней мере, пока) продолжительности, которую вы используете перед выполнением каждой задачи. Как написано, время, затрачиваемое на выполнение каждой задачи, не засчитывается в задержки, поэтому, если задачи занимают больше времени, чем задержка, вы получите задачи, выполняемые без задержки между ними. Изменить это должно быть легко, если вы хотите.
Ваша проблема понятна, потому что то, что вам нужно для того, чтобы иметь таймеры, которые не блокируют ваш цикл событий, — это цикл событий, а в C ++ еще нет стандартного. Вам нужно использовать другие фреймворки (например, Qt, Boost.Asio (?) Или непереносимые API (select () и т. Д.)) Для записи циклов событий.