在QThread中调用QThread.exec()方法是必要的吗?
-
22-09-2019 - |
题
我没有打电话 exec()
在我的代码中,但是 timer
和 QUdpSocket
工作正常。是 exec()
用来等待一个 event
接着说?
更新:这 timer
正在工作,因为我没有打电话 moveToThread(this)
于 QThread
, ,这意味着 QThread
实际上仍然是 main thread
. 。至于 QUdpSocket
好吧,我使用民意调查 functions
. 。所以它不需要与 signals
.
提示:如果你需要做 init
的东西,这需要一个 event loop
在你的 QThread
, , 你可以 delay
呼叫 moveToThread
直到你不需要 signals
再说了,这在程序加载时很实用。您也不需要在构造函数中调用它(您可以在内部调用它 run()
例如),只需复制 this QThread
指向变量的指针并使 call
稍后/其他地方使用指针。
解决方案
为了实际使用您的线程,您必须调用而不是 QApplication 执行循环 moveToThread(this)
在线程构造函数内并在受保护的内部放置一个执行循环 run()
QThread 派生类的方法。
单独的线程执行循环可防止 QApplication 循环因非 ui 相关信号和槽而变得混乱,从而延迟按钮单击的槽执行,使您的应用程序“滞后”。
笔记:通常你 总是 QThread 的子类,参见 Qt文档 了解更多信息
编辑:Qt 文档是错误的,请阅读此线程 https://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/
其他提示
您定时器和插座使用的可能,当你调用QCoreApplication::exec()
所启动主事件循环。 虽然我敢肯定有一个很好的理由来运行一个线程中的事件循环,我不能拿出一个。
在的QThread文档状态:
每个的QThread可以有自己的事件循环。你可以开始调用exec()事件循环;您可以通过调用exit停止它()或退出()。具有在一个线程的事件循环使得能够在该线程从其他线程信号连接到插槽,使用称为排队连接机构。这也使得有可能使用那些需要事件循环类,如QTimer和与QTcpSocket,在线程。但是请注意,这是不可能使用任何插件类的线程。
如果没有事件循环,有可能以发射其通过GUI线程,或含有一个事件循环不同的线程处理的信号。这意味着,一个线程必须有一个事件循环,以便其插槽是有效的。根据上面的文档,有些类,如 QTimer ,需要一个正在运行的事件循环针对你必须调用 QThread::exec()
。其他类,如 与QTcpSocket有能力使用或不使用事件循环中运行,这取决于上使用的功能。对于类的文档应说明什么,如果有的话,要求他们。
这取决于你的程序。下面是一个例子:
void MyThread::run(){
Curl * curl = new Curl();
connect( curl, SIGNAL(OnTransfer(QString)), this, SLOTS(OnTransfer(QString)) );
connect( curl, SIGNAL(OnDone()), curl, SLOTS(deleteLater()) );
curl->Download("http://google.com");
exec(); // this is an event loop in this thread, it will wait until you command quit()
}
void MyThread::OnTransfer(QString data){
qDebug() << data;
}
如果没有执行exec(),OnTransfer将永远不会被调用。但是,如果你创建卷曲外运行与的此强>(假定MyThread的父是主线程)作为亲本:
MyThread::MyThread(){
curl = new Curl(this);
connect( curl, SIGNAL(OnTransfer(QString)), this, SLOTS(OnTransfer(QString)) );
start();
}
void MyThread::run(){
curl->Download("http://google.com");
}
这也将能够运行你的预期。 OnTransfer将被调用。