【问题标题】:getting value of sensor each second c++每秒获取传感器的值c ++
【发布时间】:2017-01-22 21:09:22
【问题描述】:

我最近尝试将湿度传感器测量的数据存储到我的 MYSQL 数据库中。我已经编写了必要的 C++ 程序,从传感器获取数据,将其存储在我的 MYSQL 数据库中并获取当前的 UnixTime。

但是,我想每秒存储一次数据,并认为使用线程似乎不是解决这个问题的好方法。我也不希望 MYSQL 自动插入 UnixTime。我想继续使用我的 C++ 程序。

有没有人知道使用 C++ 在必要的 UnixTime 下每秒存储数据的更简单方法?

【问题讨论】:

  • 您不需要明确的线程 - 只需在每次阅读之间睡一秒钟。您可以使用 std::time() 获取时间。
  • 但是如果我的代码更长怎么办。假设在我向传感器询问数据之前,我有 200 行代码。如果睡眠 1 秒,那么我不会每秒收到一个值。有没有办法中断,比如在 C 中退出?所以每当 UixTime 发生变化时,我都会向传感器询问数据并将其写入我的数据库中?
  • 如果您在 *NIX 下工作,有哪些反对 std::threads 甚至是老式的 fork 的反对意见?这是在后台做事的标准方式。
  • 我只在很短的时间内编写 C++。因此,我认为可能有更简单的方法,例如中断。

标签: c++ mysql database unix-timestamp


【解决方案1】:

我也会使用线程来解决这个问题。但是,我不会依赖一个工作线程。如果您的进程运行时间超过 1 秒,会发生什么情况?

相反,我会创建一组工作线程。让每个线程等待std::condition_variable。这样,您就不会拉动线程的状态,而是依靠条件变量在它们在某些工作队列中工作时得到通知。

【讨论】:

    【解决方案2】:

    有一个专用线程很好。但这是一种无需专用线程的方法。而且这种技术也可以与专用线程一起使用。

    底线是:

    请勿在此任务中使用 sleep_for

    请改用sleep_until

    您可以获得一次正确的唤醒时间。然后在循环期间做任何你需要做的工作。并且下次通过睡眠直到比上次唤醒时间长 1 秒来唤醒(而不是睡 1 秒)。

    注意上面描述中的英文:“sleep until” vs “sleep for”。

    下面是具体化的代码:

    #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 wakeup 设置为一次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,因为您不知道其他工作需要多长时间。

    【讨论】:

    • 我遇到了 system_clock::now()+1s 的问题,我总是收到错误,找不到数字文字运算符
    • @JayJay:啊,这意味着您使用的是 C++14 之前的标准。不是问题。将秒{1} 替换为 1,您就可以开始了。没有功能或性能差异。只是 C++14 添加了语法糖。
    【解决方案3】:

    线程实际上是后台任务的巧妙解决方案。考虑这个例子:

    #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();
    } 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-20
      • 1970-01-01
      • 2012-09-21
      • 1970-01-01
      • 1970-01-01
      • 2015-06-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多