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

问题描述 投票:6回答:3

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

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

提示:如果你需要做init的东西,需要你的event loop中的QThread,你可以delay调用moveToThread,直到你不再需要signals,这在程序加载时很实用。您也不需要在构造函数中调用它(例如,您可以在run()中调用它),只需将this QThread指针复制到变量,然后使用指针将call放在其他地方/其他地方。

multithreading qt qthread
3个回答
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/


4
投票

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

QThread documentation说:

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

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


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。但是如果你的create curl在外面运行(假设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将被调用。

© www.soinside.com 2019 - 2024. All rights reserved.