在QThread中调用QThread.exec()方法是必要的吗?

时间:2010-02-26 05:49:00

标签: multithreading qt qthread

我没有在我的代码中调用exec(),但timerQUdpSocket工作正常。 exec()曾经等待event继续吗?

更新:timer正在运作,因为我没有在moveToThread(this)上调用QThread,这意味着QThread实际上仍然是main thread的一部分}。至于QUdpSocket我使用轮询functions。所以它不需要使用signals

提示:如果您需要执行init内容,这需要event loop QThreaddelay可以moveToThread致电signals我需要run(),这在程序加载时很实用。您也不需要在构造函数中调用它(例如,您可以在this QThread内调用它),只需将call指针复制到变量并在以后/其他地方生成{{1}}使用指针。

3 个答案:

答案 0 :(得分:4)

您的计时器和套接字可能正在使用调用QCoreApplication::exec()时启动的主事件循环。 虽然我确信有一个很好的理由在一个线程中运行一个事件循环,但我无法想出一个。

QThread documentation州:

  

每个QThread都有自己的事件循环。您可以通过调用exec()来启动事件循环;你可以通过调用exit()或quit()来停止它。在线程中使用事件循环可以使用称为排队连接的机制将来自其他线程的信号连接到此线程中的插槽。它还可以在线程中使用需要事件循环的类,例如QTimer和QTcpSocket。但请注意,无法在线程中使用任何窗口小部件类。

如果没有事件循环,则可以发出由GUI线程处理的信号,或者包含事件循环的不同线程。这意味着一个线程必须有一个事件循环,以使其插槽有效。根据上面的文档,某些类(如QTimer)需要一个运行的事件循环,您必须为其调用QThread::exec()。其他类(如QTCPSocket)具有使用或不使用事件循环运行的功能,具体取决于所使用的函数。这些类的文档应该表明它们有什么要求。

答案 1 :(得分:2)

为了实际使用你的线程,而不是QApplication执行循环,你必须在线程构造函数中调用moveToThread(this)并在QThread派生类的受保护run()方法中放置一个执行循环

单独的线程执行循环可防止QApplication循环与非ui相关的信号和插槽混乱,从而延迟.e.g按钮单击的插槽执行,使您的应用程序“滞后”。

注意:通常总是子类QThread,有关详细信息,请参阅Qt doc

编辑:Qt doc错误,请阅读此帖子https://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/

答案 2 :(得分:0)

这取决于你的程序。这是一个例子:

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将被调用。