使用串口进行通信
子线程实现
产生错误的代码
void Check_Serial_Monitor_Thread::run()
{
m_odd_serial_list.clear();
QStringList tmp_str_list;
while(open_flag){// 不断检测是否有新的可用串口出现
tmp_str_list.clear();
// 可以再详细一下,检测链接进来然后发生断开的情况。暂时未实现
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
tmp_str_list += info.portName();
}
if(tmp_str_list != m_odd_serial_list){// 更新下拉框
m_odd_serial_list = tmp_str_list;// 更新之前的保存的数据
Custom_Tools::Print("Update available serial port!");
emit Have_Change_Serial(tmp_str_list);
}
}
}
connect(this,&Widget::Stop_Serial_Monitor_Thread,
m_check_serial_thread,&Check_Serial_Monitor_Thread::Stop_Cur_Thread,
Qt::QueuedConnection);
void Check_Serial_Monitor_Thread::Stop_Cur_Thread()
{
Custom_Tools::Print("Quit Slot");
open_flag = false;
}
Widget::~Widget()
{
emit Stop_Serial_Monitor_Thread();
// 将串口关闭
if(ui->operate_serial_switch_btn->text() == QString("关闭")){
Operator_Serial_Switch();
}
m_check_serial_thread->quit();
m_check_serial_thread->wait();
m_serial_comm_thread.quit();
m_serial_comm_thread.wait();
delete ui;
}
原因猜测
事实证明,我的猜想是正确的。
// 关闭串口检测线程的信号
connect(this,&Widget::Stop_Serial_Monitor_Thread,
m_check_serial_thread,&Check_Serial_Monitor_Thread::Stop_Cur_Thread,
Qt::BlockingQueuedConnection);
Qt::BlockingQueuedConnection Same as Qt::QueuedConnection, except that the signalling thread blocks until the slot returns. This connection must not be used if the receiver lives in the signalling thread, or else the application will deadlock.
与 Qt::QueuedConnection 相同,除了信号线程阻塞直到槽返回。 如果接收器位于信号线程中,则不得使用此连接,否则应用程序将死锁。
解决方式
emit Stop_Serial_Monitor_Thread();
QApplication::processEvents();
Tells the thread’s event loop to exit with return code 0 (success). Equivalent to calling QThread::exit(0). This function does nothing if the thread does not have an event loop.
告诉线程的事件循环退出,返回代码为0(成功)。相当于调用QThread::exit(0)。 如果线程没有事件循环,此函数将不执行任何操作。
Blocks the thread until either of these conditions is met: The thread associated with this QThread object has finished execution (i.e. when it returns from run()). This function will return true if the thread has finished. It also returns true if the thread has not been started yet. The deadline is reached. This function will return false if the deadline is reached. A deadline timer set to QDeadlineTimer::Forever (the default) will never time out: in this case, the function only returns when the thread returns from run() or if the thread has not yet started. This provides similar functionality to the POSIX pthread_join() function.
阻塞线程,直到满足以下任一条件: 与此QThread对象关联的线程已完成执行(即,当它从run()返回时)。如果线程已完成,此函数将返回true。如果线程还没有启动,它也会返回true。 截止日期已到。如果达到截止日期,此函数将返回false。
结束
这里感谢下韬哥,带着我一起调试,解决了这个困扰了我几天的问题。
涉及到的代码
Widget::~Widget()
{
emit Stop_Serial_Monitor_Thread();
// 终止串口检测线程信号
// 将串口关闭
if(ui->operate_serial_switch_btn->text() == QString("关闭")){
Operator_Serial_Switch();
}
m_check_serial_thread.quit();
m_check_serial_thread.wait();
m_serial_comm_thread.quit();
m_serial_comm_thread.wait();
delete ui;
}
void Check_Serial_Monitor_Worker::Stop_Cur_Thread()
{
Custom_Tools::Print("Check Serial Stop");
m_timer->stop();
}
解决