多线程 – 由于另一个QThread,QApplication线程冻结
在我的Qt应用程序中,我创建了一个QThread,它应该定期执行一些繁重的计算任务.主QApplication线程应该维护GUI(不包括在示例中)并执行一些定期更新.两个线程都有自己的定时器来启用常规的update()调用.
问题:当工作线程的计算工作负载超过某个临界值时,我的主线程停止接收计时器事件. 示例代码如下.当主线程调用update()时,它输出“Main”,工作线程调用“Worker”.如果你运行它,你会看到“工人”定期打印,“主”正好出现两次(一个在开头,一个在约5秒).在全功能GUI应用程序的情况下,这实际上意味着完全GUI冻结. 一些观察. >通过对内循环(而不是1000)设置100限制来减少工作量将解决问题(两个update()方法将定期调用). 所以,你可以看到我有几个解决方法,但我很感激有人解释我原始代码的问题是什么.我希望线程能够独立地执行它们的事件循环.我知道我通过一个很长的update()操作来阻止工作线程事件循环,但为什么它会影响主线程? 附:是的,我知道QConcurrent替代方案.但我只是想明白. TEST.CPP #include <windows.h> #include <QApplication> #include "test.h" HANDLE mainThread_ = INVALID_HANDLE_VALUE; QApplication *app_ = 0; MyObj *obj_ = 0; MyThread *thread_ = 0; MyObj::MyObj() : timer_(0) { timer_ = new QTimer(0); connect(timer_,SIGNAL(timeout()),this,SLOT(update())); timer_->start(10); } void MyObj::update() { printf("Mainn"); } void MyThread::run() { timer_ = new QTimer(0); connect(timer_,SLOT(update())); timer_->start(10); exec(); } void MyThread::update() { printf("Workern"); // do some hard work float f = 0.f; for (int i=0; i < 100000; ++i) { for (int j=0; j < 1000; ++j) { f += i * j; } } } int main() { int argc = 0; app_ = new QApplication(argc,0); obj_ = new MyObj(); thread_ = new MyThread(); thread_->start(); QApplication::exec(); return 0; } test.h #include <QTimer> #include <QThread> class MyObj : public QObject { Q_OBJECT public: MyObj(); public slots: void update(); private: QTimer *timer_; }; class MyThread : public QThread { Q_OBJECT public: void run(); public slots: void update(); private: QTimer *timer_; }; UPD:我从尊敬的成员那里得到了一些答案(见下文).现在我想澄清一下错误的想法特别破坏了我的代码. 正如您所看到的,该计划有两个线程,每个线程定期运行一些update()过程.我的错误是将update()视为一些过程,它是一个插槽.特定对象的一个??插槽,它具有自己的线程亲和性,这意味着它的主体将在该线程中执行(除非使用Qt :: DirectConnection调度信号).现在,似乎我已经用计时器完成了它 – 每个都属于不同的线程 – 但是用update()搞砸了.所以我最终在主线程中执行了两个update()程序.显然,在某些时候,事件循环会被定时器事件淹没,并且永远不会完成迭代. 至于解决方案.如果您已经阅读了“You’re doing it wrong”(并且您确实应该),您知道将所有逻辑实现在一个对象中是非常方便的,该对象不是从QThread继承而是单独创建并使用moveToThread()连接到QThread.我个人认为,如果你记住你的对象只控制线程但不属于它,那么从QThread继承子类没什么问题.因此,它不是您希望在该线程中执行的代码的位置. 解决方法
这里的第一个问题是你继承自QThread,因为它声明了
here,“you’re doing it wrong”.
您遇到的问题源于线程关联(运行对象的线程).例如,如果您要从QThread继承并在构造函数中创建对象,而不对该对象进行父对象,则该对象将在主线程中运行,而不是在新线程中运行.所以在MyThread构造函数中你会有: – MyThread::MyThread() : timer_(0) { timer_ = new QTimer(0); connect(timer_,SLOT(update())); timer_->start(10); } 这里的计时器(timer_)将在主线程上运行,而不是新线程. 解决问题的最佳方法是将类更改为继承自QObject,然后将该对象移动到新线程. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |