QThread 中的插槽同时运行
Slots inside QThread running concurrently
我有两个类,一个处理程序和一个工作线程,通过信号和插槽连接。下面是一个简化版本(伪代码(:
处理程序构造函数:
Handler::Handler(QObject *parent) : QObject(parent)
{
m_workerThread = new QThread;
m_worker = new Worker;
m_worker->moveToThread(m_workerThread);
m_workerThread->start();
connect(this, &Handler::doWork, m_worker, &Worker::doWork);
connect(this, &Handler::stopWork, m_worker, &Worker::stopWork);
emit doWork();
}
工人
void Worker::doWork()
{
qDebug()<<"------"
qDebug()<<"Start do work executing in: "<<QThread::currentThreadId();
//doing some work
m_timer->start();//a singleshot timer that calls doWork() on timeout
qDebug()<<"work done";
qDebug()<<"------"
}
void Worker::stopWork()
{
qDebug()<<"Stop timer executing in: "<<QThread::currentThreadId();
m_timer->stop();
}
所以基本上工作是在从处理程序发出"doWork"之后开始的。"doWork"插槽有一个单次计时器,可在一定时间后再次调用相同的函数。一段时间后,处理程序发出"停止工作"信号。这是我的调试输出:
------
Start do work executing in: 0x65602450
work done
------
------
Start do work executing in: 0x65602450
work done
------
------
Start do work executing in: 0x65602450
work done
------
------
Start do work executing in: 0x65602450
stop work emitted from handler in: 0x750a7000
Stop timer executing in: 0x65602450
work done
------
------
Start do work executing in: 0x65602450
work done
------
etc...
所以我不明白的是,我的工作线程怎么可能同时执行两个插槽(doWork 和 stopWork(?不应该发布停止工作信号并等待线程在执行"停止工作"插槽之前变为空闲吗?
不幸的是,我无法使用最小的工作示例重现这一点,但我希望从我发布的代码中可以清楚地看到我缺少什么。
同样从我的测试中,我认为这种情况在 30-40% 的情况下都会发生。
使用 QMutex 和/或 QSemaphore 等线程同步类可能会解决您的问题。
例如,如果您在处理程序类中创建了一个 QMutex 并将其传递给工作线程:
Handler::Handler(QObject *parent) : QObject(parent)
{
//Class variable : QMutex* mutex
mutex = new QMutex();
m_workerThread = new QThread;
m_worker = new Worker;
m_worker->moveToThread(m_workerThread);
m_workerThread->start();
connect(this, &Handler::doWork, m_worker, &Worker::doWork);
connect(this, &Handler::stopWork, m_worker, &Worker::stopWork,Qt::BlockingQueuedConnection);
emit doWork(mutex);
}
然后从另一个线程内部调用这个常见的 QMutex 锁定机制:
void Worker::doWork(QMutex* mutex)
{
mutex->lock();
qDebug()<<"------"
qDebug()<<"Start do work executing in: "<<QThread::currentThreadId();
//doing some work
m_timer->start();//a singleshot timer that calls doWork() on timeout
qDebug()<<"work done";
qDebug()<<"------"
mutex->unlock();
}
并在 Handler 类中使用相同的逻辑,就在发出"停止"信号之前:
...
mutex->lock();
emit stopWork();
mutex->unlock();
...
这样,您可以避免不必要的并发。
这里的 BlockingQueuedConnection 标志可确保在停止作业完成之前主线程不会前进,因此在作业完成之前不会解锁互斥锁。
这是我在处理并发情况和数据竞赛时尝试使用的逻辑,我希望它也能对您有所帮助。
相关文章:
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- 如何在没有信号的情况下从C++执行QML插槽
- 从Q_INVOKABLE功能或插槽中更改QQuick图像源
- 升压信号2将插槽传递到成员功能以断开连接
- 如何在qt中将信号和插槽与另一个对象连接 --解决了
- C++ 信号和插槽不工作:插槽不响应事件
- NS3 插槽混淆(需要帮助理解)
- QObject::连接无法将信号连接到*this*对象的插槽
- QT 插槽未在主线程上调用
- 通过插槽和信号在不同线程中的两个qt对象之间进行通信
- 控制带有信号/插槽的Qt QML滑动视图
- Qt 信号/插槽问题
- QT5 信号不会激活插槽内的功能
- Qt5:连接:如果插槽的参数少于信号,如何使用"连接"
- 需要实例化不同类/对象并在启动时确定的硬件插槽的设计模式
- C++/Qt项目中的连接功能中不存在插槽?(已经重新运行了制作)
- QThread 中的插槽同时运行
- Qt如何使一个按钮响应时,插槽连接到它的click()信号正在运行
- Qt-如何同时运行两个插槽而不显式实现线程
- 如何使用 QWaitCondition 实现永久运行的 QThread,但在执行此操作时仍然需要捕获另一个插槽