我正在编写一个Windows 10应用程序,它通过串行从4个不同的传感器(编码器和IMU)收集数据。我是在c ++ 11中的Visual Studio中编写的。每个传感器有一个线程,可以在无限循环中连续从中获取数据。
由于我是新手,我目前正在努力以某种方式“收集”单个线程中的数据。我发现我可以使用条件变量来指示另一个线程(在我的情况下,我假设我会在每个传感器完成时发出主线程信号)。在这种情况下,我是否必须将数据存储在全局变量中,并在我写入(从传感器线程)并从中读取(在主循环中)时使用互斥锁保护它?
但是,我担心这个过程对我的应用程序来说可能太慢(每个传感器每1-2毫秒获取一次新数据),因此在主线程读取时锁定数据的过程中,我会丢失一些数据。 (在每个传感器线程内)将数据存储在局部变量中然后将此变量复制到全局变量,并且主线程仅从第二个变量读取是否有意义?如果这些是愚蠢的问题,我道歉,但我真的需要帮助。任何示例代码都将非常感激。
答案 0 :(得分:1)
这看起来就像我要实施的那样。如果输入之间有毫秒(这是一段很长的时间),我真的怀疑你会遇到吞吐量问题。
如果有人发现下面有任何微妙的错误,请告诉我。
#include <thread>
#include <iostream>
#include <chrono>
#include <queue>
#include <mutex>
#include <vector>
#include <condition_variable>
using namespace std::chrono_literals;
using std::vector;
using std::thread;
using std::unique_lock;
using std::mutex;
using std::condition_variable;
using std::queue;
class WorkQueue
{
condition_variable work_available;
mutex work_mutex;
queue<int> work;
public:
void push_work(int item)
{
unique_lock<mutex> lock(work_mutex);
bool was_empty = work.empty();
work.push(item);
lock.unlock();
if (was_empty)
{
work_available.notify_one();
}
}
int wait_and_pop()
{
unique_lock<mutex> lock(work_mutex);
while (work.empty())
{
work_available.wait(lock);
}
int tmp = work.front();
work.pop();
return tmp;
}
};
int main() {
WorkQueue work_queue;
auto producer = [&]() {
while (true) {
work_queue.push_work(10);
std::this_thread::sleep_for(2ms);
}
};
vector<thread> producers;
producers.push_back(std::thread(producer));
producers.push_back(std::thread(producer));
producers.push_back(std::thread(producer));
producers.push_back(std::thread(producer));
std::thread consumer([&]() {
while (true)
{
int work_to_do = work_queue.wait_and_pop();
std::cout << "Got some work: " << work_to_do << std::endl;
}
});
std::for_each(producers.begin(), producers.end(), [](thread &p) {
p.join();
});
consumer.join();
}
答案 1 :(得分:0)
我会通过使用boost::asio库在每个传感器上设置异步读取来处理这个问题。异步读取完成后,它会调用读取处理程序来解析数据,然后设置另一个异步读取。所有读取处理程序都在同一个线程中运行 - 这使生活变得更加简单。