这是我的简化类,用于检测完整程序中的问题:
SimpleThread.h
class SimpleThread {
public:
SimpleThread();
~SimpleThread();
void startThread();
void threadFn();
private:
SerialPort mySerial;
std::thread myThread;
int count;
std::mutex myMutex;
};
SimpleThread.cpp
SimpleThread::SimpleThread(): mySerial("/dev/ttyACM0") {
count = 0;
mySerial.Open(//Here correct params//);
}
SimpleThread::~SimpleThread() {}
void SimpleThread::threadFn() {
char cp;
while (true) {
cp = mySerial.ReadByte(0);
std::cout << count++ << " " << cp << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
void SimpleThread::startThread() {
myThread = std::thread(&SimpleThread::threadFn, this);
myThread.detach();
}
的main.cpp
int main() {
SimpleThread thr;
thr.startThread();
while (true) {
std::cout << "Waiting 5 seconds" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(5));
}
}
我的例子的主要思想:我使用类成员函数作为线程函数从打开的串口读取数据。没有从串口读取使用这个类没有问题:主循环每隔5秒打印一次消息,而线程循环(类中的函数)打印5个数字。
现在我想实现从串口读取,而我的主循环将要做其他事情。为了以串行方式进行读/写,我使用了this而不是最新的串行库。
在这种情况下,类开始对我意外工作:主循环(应该每5秒显示一次消息)显示其消息更快然后线程循环(大约40次,1秒)。此代码工作错误导致主循环在1秒内(读取字节后)打印消息40次,尽管有睡眠功能。
所以我的问题是:问题的根源在哪里?我应该使用另一个串行库还是有一些与我不知道的中断相关的功能?
编辑:如果我使用下一个循环进行读取并检查数据是否可用,则在每个读取字节后打印主循环。看起来在线程循环中读取字节会中断主循环并取消休眠。
if ( mySerial.IsDataAvailable() ) {
cp = mySerial.ReadByte(0);
std::cout << count++ << " " << cp << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
编辑2:此外,我测试只是打开串口,但没有读取串行循环(在两秒钟内线程循环中更改暂停)
if ( mySerial.IsDataAvailable() ) {
std::cout << count++ << " " << cp << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
}
在这种情况下,主循环每秒打印一次。只有在没有打开串口的情况下才会出现问题。
答案 0 :(得分:0)
libserial使用基于信号的异步I / O(确切地说SIGIO
)并且GCC 5中存在一个错误(#66803)std::this_thread::sleep_for
被信号打断了。它已在GCC 6中修复。
可能的解决方案是:
使用错误66803中提到的解决方法或尝试sleep_until
:
auto wakeup_time = std::chrono::steady_clock::now() + std::chrono::seconds(1);
std::this_thread::sleep_until(wakeup_time);