2017-01-22 7 views
0

Недавно я пытался хранить данные, измеренные датчиком влажности, в моей базе данных MYSQL. Я уже запрограммировал необходимую C++ pogramm, получая данные от датчика, сохраняя его в моей базе данных MYSQL и получая текущий UnixTime.получение значения датчика каждую секунду C++

Тем не менее, я хотел бы хранить данные каждую секунду и думать, используя поток, не кажется аккуратным решением для этой проблемы. Я также не хочу, чтобы MYSQL автоматически вставлял UnixTime. Я хотел бы продолжать использовать мою C++-программу для этого.

Кто-нибудь знает более простой способ хранения данных каждую секунду с помощью UnixTime с помощью C++?

+0

Вам не нужен явный поток - просто спать на секунду между каждым чтением. Вы можете получить время с помощью std :: time(). –

+0

Но что делать, если мой код длиннее.Скажем, у меня есть 200 строк кода, прежде чем я попрошу датчик для данных. Если сон 1 секунда, то я не получаю каждую секунду значение. Есть ли способ прервать, например, один выход на C? Поэтому всякий раз, когда изменяется UixTime, я спрашиваю у своего датчика данные и записываю их в свою базу данных? – JayJay

+0

Каковы возражения против 'std :: threads' или даже старой старомодной [fork] (https://linux.die.net/man/2/fork), если вы работаете в * NIX? Это стандартный способ делать вещи в фоновом режиме. – Oncaphillis

ответ

0

Резьбы на самом деле являются аккуратным решением для фоновых задач. Рассмотрим этот пример:

#include <iostream> 
#include <thread> 
#include <chrono> 

void everySecondTask() { 
    while (true) { 
    // Do actual work here, e.g. get sensor data and write to db 
    std::cout << "second passed" << std::endl; 

    std::this_thread::sleep_for(std::chrono::seconds(1)); 
    } 
} 

int main() { 
    // operations and sleep in everySecondTask is done in different thread, code 
    // in main is not paused. 
    std::thread background(everySecondTask); 

    // do you 200 lines of code here, while task is called every second 

    background.join(); 
} 
1

Я также использовал бы резьбу для решения этой проблемы. Однако я бы не стал полагаться на один рабочий поток. Что произойдет, если ваш процесс займет больше 1 секунды для запуска?

Вместо этого я бы создал группу рабочих потоков. Попросите каждого потока ждать на std::condition_variable. Таким образом, вы не занимаетесь статусом своих потоков и вместо этого полагаетесь на условную переменную, которая должна быть уведомлена, когда они работают в некоторой рабочей очереди.

1

Наличие выделенной нити в порядке. Но вот способ сделать это без специального потока. И этот метод также можно использовать с выделенным потоком.

Суть:

Не используйте 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, потому что вы не знаете, сколько времени займет эта другая работа.

+0

У меня возникла проблема, когда дело доходит до system_clock :: now() + 1s. Я всегда получаю ошибку, неспособную найти оператор числовой литерал – JayJay

+0

@JayJay: А это означает, что вы используете стандарт до C++ 14. Не проблема. Замените секунды {1} на 1 секунду, и вам будет хорошо идти. Никакой функциональной или разницы в производительности. Просто C++ 14 добавил этот синтаксический сахар. –

 Смежные вопросы

  • Нет связанных вопросов^_^