QThread 与 QTimer 和 QSerial - 育儿
QThread with QTimer and QSerial - parenting
我正在尝试将 "self contained" 通信对象分配到不同的线程中,以使其不受 GUI 处理延迟的影响。
因此,在 "AppCore" 对象创建中,我创建了一个 "CommCore" 没有父对象的对象:
cAppCore::cAppCore(QObject *parent) : QObject(parent)
{
....
CommCore = new cCommCore;
(here I do signal-slot connections between CommCore and AppCore)
....
}
在 CommCore 构造函数中,我执行以下操作:
cCommCore::cCommCore(QObject *parent) : QObject(parent)
{
CommThread = new QThread(this);
CommSerial = new QSerialPort(this);
CommTimer = new QTimer(this);
connect(CommSerial,&QSerialPort::readyRead,this,&cCommCore::ProcessRXByte);
connect(CommSerial, static_cast<void (QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error), this, &cCommCore::HandleSerialError);
connect(CommTimer, &QTimer::timeout, this,&cCommCore::TimerTimeout);
CommTimer->start(OFFLINE_POLL_TIME);
this->moveToThread(CommThread);
CommThread->start(QThread::HighPriority);
}
现在我的问题:
1- 可以让线程处理程序对象成为移动对象的子对象吗?因为它是在 GUI 线程(调用构造函数的地方)中创建的,然后移动到由它自己处理的线程(考虑到如果我需要对它进行任何控制,我将从 CommCore 对象内部处理它)
2- 可以在构造函数中启动计时器(它与计时器构造函数在同一个线程中,GUI 线程),然后立即将所有内容移动到新线程吗?
3-如果我想稍后启动计时器,唯一的方法是通过信号槽吗?其中一个信号在 GUI 线程中发出并连接到一个 CommCore 插槽(然后将在 CommCore 线程中排队并执行)
4- 考虑到我的 CommCore 对象和 AppCore(GUI 线程)之间的所有交互都是通过信号槽(线程安全的)进行的,这在概念上是正确的吗? (对象的想法将其自身及其子对象移动到新线程等)
5- 我基于池(由计时器计时)的串行通信例程将不受 GUI 处理延迟的影响? (我的意思是,Serial 和 Timer 对象产生的事件的产生和处理不会有延迟?)
this->moveToThread(CommThread);
如果对象 this 没有父对象,将会成功。所以你需要改变你的构造函数的签名。除此之外没关系,因为对象与其子项一起移动...
定时器不应该这样启动,因为它被移到了不同的线程中。您应该使用 invokeMethod 以便它是执行操作的正确线程
QMetaObject::invokeMethod(CommTimer, "start");
对于您剩下的问题,所有答案都是肯定的。只要您使用信号并使用 invokeMethod 进行调用,就好像线程正在从 runnable 和 运行 它们的池中获取。
因此线程安全且不受主线程中断的影响。
我正在尝试将 "self contained" 通信对象分配到不同的线程中,以使其不受 GUI 处理延迟的影响。
因此,在 "AppCore" 对象创建中,我创建了一个 "CommCore" 没有父对象的对象:
cAppCore::cAppCore(QObject *parent) : QObject(parent)
{
....
CommCore = new cCommCore;
(here I do signal-slot connections between CommCore and AppCore)
....
}
在 CommCore 构造函数中,我执行以下操作:
cCommCore::cCommCore(QObject *parent) : QObject(parent)
{
CommThread = new QThread(this);
CommSerial = new QSerialPort(this);
CommTimer = new QTimer(this);
connect(CommSerial,&QSerialPort::readyRead,this,&cCommCore::ProcessRXByte);
connect(CommSerial, static_cast<void (QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error), this, &cCommCore::HandleSerialError);
connect(CommTimer, &QTimer::timeout, this,&cCommCore::TimerTimeout);
CommTimer->start(OFFLINE_POLL_TIME);
this->moveToThread(CommThread);
CommThread->start(QThread::HighPriority);
}
现在我的问题:
1- 可以让线程处理程序对象成为移动对象的子对象吗?因为它是在 GUI 线程(调用构造函数的地方)中创建的,然后移动到由它自己处理的线程(考虑到如果我需要对它进行任何控制,我将从 CommCore 对象内部处理它)
2- 可以在构造函数中启动计时器(它与计时器构造函数在同一个线程中,GUI 线程),然后立即将所有内容移动到新线程吗?
3-如果我想稍后启动计时器,唯一的方法是通过信号槽吗?其中一个信号在 GUI 线程中发出并连接到一个 CommCore 插槽(然后将在 CommCore 线程中排队并执行)
4- 考虑到我的 CommCore 对象和 AppCore(GUI 线程)之间的所有交互都是通过信号槽(线程安全的)进行的,这在概念上是正确的吗? (对象的想法将其自身及其子对象移动到新线程等)
5- 我基于池(由计时器计时)的串行通信例程将不受 GUI 处理延迟的影响? (我的意思是,Serial 和 Timer 对象产生的事件的产生和处理不会有延迟?)
this->moveToThread(CommThread);
如果对象 this 没有父对象,将会成功。所以你需要改变你的构造函数的签名。除此之外没关系,因为对象与其子项一起移动...
定时器不应该这样启动,因为它被移到了不同的线程中。您应该使用 invokeMethod 以便它是执行操作的正确线程
QMetaObject::invokeMethod(CommTimer, "start");
对于您剩下的问题,所有答案都是肯定的。只要您使用信号并使用 invokeMethod 进行调用,就好像线程正在从 runnable 和 运行 它们的池中获取。
因此线程安全且不受主线程中断的影响。