6

我没有调用exec()我的代码,但是timerandQUdpSocket工作正常。是exec()用来等待一个event继续吗?

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

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

4

3 回答 3

4

您的计时器和套接字可能正在使用您调用时启动的主事件循环QCoreApplication::exec()尽管我确信在线程中运行事件循环是有充分理由的,但我想不出一个。

QThread 文档指出:

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

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

于 2010-02-26T06:18:50.820 回答
2

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

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

注意:通常你总是继承 QThread,查看Qt 文档了解更多信息

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

于 2010-02-26T09:04:19.593 回答
1

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

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。但是,如果您在外部创建 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。

于 2010-08-16T07:08:10.187 回答