Наличие выделенной нити в порядке. Но вот способ сделать это без специального потока. И этот метод также можно использовать с выделенным потоком.
Суть:
Не используйте sleep_for
для этой задачи
Используйте sleep_until
вместо этого.
Вы можете получить соответствующее время пробуждения один раз. И затем сделайте все, что вам нужно сделать во время цикла. И проснуться в следующий раз, спать до 1 с дольше, чем последнее время пробуждения (вместо того, чтобы спать в течение 1 с).
Обратите внимание на английский в приведенном выше описании: «спите до» и «спать».
Вот код, чтобы сделать этот бетон:
#include "date.h"
#include <iomanip>
#include <iostream>
#include <random>
#include <thread>
std::mt19937_64 eng;
void
do_other_work()
{
using namespace std;
using namespace std::chrono;
static uniform_int_distribution<> dist{2, 600};
this_thread::sleep_for(milliseconds{dist(eng)});
}
std::pair<double, date::sys_seconds>
get_humidity()
{
using namespace std;
using namespace std::chrono;
using namespace date;
static uniform_real_distribution<> dist;
return {dist(eng), round<seconds>(system_clock::now())};
}
int
main()
{
using namespace std;
using namespace std::chrono;
using namespace date;
cout << fixed << setprecision(2);
auto wakeup = system_clock::now() + 1s;
while (true)
{
auto data = get_humidity();
cout << data.first << " : " << data.second << '\n';
do_other_work();
this_thread::sleep_until(wakeup);
wakeup += 1s;
}
}
Я добавил header-only library "date.h" просто, чтобы сделать его легко форматировать текущую UnixTime метку времени. Но вышеприведённая точка должна установить time_point
один раз с system_clock::now()
, а затем просто увеличить его на 1s
на каждой итерации и использовать this_thread::sleep_until
, чтобы спать до этого time_point
. Пока ваша вторая работа не превышает 1s, эта программа будет надежно выходные данные один раз в секунду:
0.79 : 2017-01-23 02:06:21
0.40 : 2017-01-23 02:06:22
0.02 : 2017-01-23 02:06:23
0.27 : 2017-01-23 02:06:24
0.14 : 2017-01-23 02:06:25
0.86 : 2017-01-23 02:06:26
...
Если вы хотите положить get_humidity()
в другом потоке, что по-прежнему хорошо. Но чтобы сохранить точный отчет за/сек в этом другом потоке (который все еще должен выполнять другую работу), используйте sleep_until
вместо sleep_for
, потому что вы не знаете, сколько времени займет эта другая работа.
Вам не нужен явный поток - просто спать на секунду между каждым чтением. Вы можете получить время с помощью std :: time(). –
Но что делать, если мой код длиннее.Скажем, у меня есть 200 строк кода, прежде чем я попрошу датчик для данных. Если сон 1 секунда, то я не получаю каждую секунду значение. Есть ли способ прервать, например, один выход на C? Поэтому всякий раз, когда изменяется UixTime, я спрашиваю у своего датчика данные и записываю их в свою базу данных? – JayJay
Каковы возражения против 'std :: threads' или даже старой старомодной [fork] (https://linux.die.net/man/2/fork), если вы работаете в * NIX? Это стандартный способ делать вещи в фоновом режиме. – Oncaphillis