是否可以在不进行子类化的情况下使用QThread实现轮询
Is it possible to implement polling with QThread without subclassing it?
我有一个类,它是某个设备的抽象。
class Device
{
public:
...
void Start();
void Stop();
void MsgLoop();
signals:
void sMsgArrived();
}
Start()和Stop()是从GUI线程调用的。Start()开始新线程,该线程运行MsgLoop()。它看起来像这样:
void MsgLoop()
{
forever {
if(SUCCESS == ReadMsg()) //synchronous, non-blocking
{
ProcessMsg(); //quite fast
emit sMsgArrived(); //this signal is connected with a slot in GUI thread
}
}
}
当调用Stop()时,程序应该从MsgLoop()返回并停止线程。如何在不进行子类化的情况下使用QThread实现这一点?
通常,您必须决定谁将负责管理线程。是设备还是主窗口?或者可能是某个设备管理器。在您的情况下,设备可能应该管理自己的线程,所以如果您不想将其子类化,请使用composition:
class Device : QObject
{
Q_OBJECT
public:
Device(QObject * parent = NULL);
void Start();
void Stop();
private slots:
void MsgLoop();
signals:
void sMsgArrived();
private:
QThread thread;
bool stopThread;
};
Device::Device(QObject * parent) : QObject(parent)
{
moveToThread(&thread);
connect(&thread, SIGNAL(started()), this, SLOT(MsgLoop()));
}
void Device::Start()
{
stopThread = false;
thread.start();
}
void Device::Stop()
{
stopThread = true;
thread.wait(); // if you want synchronous stop
}
void Device::MsgLoop()
{
// your loop
while(!stopThread)
if(SUCCESS == ReadMsg())
{
ProcessMsg();
emit sMsgArrived();
}
QThread::currentThread->quit();
}
注意:只有当ReadMsg
真的是非阻塞的时,线程停止才会起作用。如果您稍后决定切换到阻塞读取(这可能适用于大多数情况),您将不得不想出另一种方法来停止线程。
如果您查看此链接,您可以看到在单独的线程中运行方法而无需对QThread进行子类化。
但是,您所要求的是永远运行一个消息循环。
如果您遵循给定的示例,您可以在不进行子类化的情况下运行循环,但QThread对象永远不会进入其自己的消息循环,因为它永远不会从您的插槽返回。所以这里有一个例子,但我认为这将是一个糟糕的设计
class Device : public QObject
{
Q_OBJECT
public:
Device(QObject* parent = 0);
~Device();
public Q_SLOTS:
void MsgLoop();
};
QThread* thread = new QThread;
Device* device = new Device;
void Widget::onBtnStartClicked()
{
device->moveToThread(thread);
//This will call start method of Device
connect(thread, SIGNAL(started()), device, SLOT(MsgLoop()));
//This will start the event loop of thread
thread->start();
}
void Widget::onBtnStopClicked()
{
//Tells the thread to exit
thread->exit(0);
}
如果您想永远运行循环,恐怕您必须对QThread进行子类化。
IMHO你不应该。轮询需要永远处于循环中。您必须在QThread的run函数中执行此操作,这样就无法在不首先进行子类的情况下重新实现函数。即使你尝试用单次计时器来解决这个问题,我也不建议你这样做。你最好(这就是我喜欢做的)对QThread进行子类化,调用moveToThread(),而不是调用exec()并运行一个永久循环。有关此示例,请参阅qt中的Fortune Blocking Client示例。如果不在QThread上调用moveToThread(),那么QThread对象仍然驻留在GUI主线程中,并且它们共享相同的事件循环(使用轮询函数时这很糟糕)。在不调用exec()的情况下调用moveToThread(QThread)意味着QThread将不会有事件循环(在您的情况下这很好)。调用exec()将启动它自己的事件循环,但不用于轮询方案,您将离开run函数。
- 在没有太多条件句的情况下,我如何避免被零除
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 在未初始化映射的情况下,将值插入到映射的映射中
- 是默认情况下分配给char数组常量的值
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- 如何在不产生任何垃圾的情况下获得C中的像素
- 在已经使用Git的情况下减少编译时间
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- 如何在没有信号的情况下从C++执行QML插槽
- 如何在不知道向量大小的情况下输入向量内部的向量?
- 为什么在某些情况下不写入此文件?
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 在没有Xcode的情况下在Mac捆绑包中嵌入框架
- UE4-如何在给定4个屏幕坐标的情况下缩放纹理或材质
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- 在C++中如何在没有pow的情况下进行基础计算
- 松弛原子与无同步情况下的记忆连贯性
- 了解如何在不冻结事件循环的情况下在 QThread 中休眠/等待
- 当应用程序在没有适当的 wait() 调用的情况下关闭时,QThread 会发生什么
- 是否可以在不进行子类化的情况下使用QThread实现轮询