Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 在QThread中是否需要调用QThread.exec()方法?_Multithreading_Qt_Qthread - Fatal编程技术网

Multithreading 在QThread中是否需要调用QThread.exec()方法?

Multithreading 在QThread中是否需要调用QThread.exec()方法?,multithreading,qt,qthread,Multithreading,Qt,Qthread,我没有在代码中调用exec(),但是计时器和QUdpSocket工作正常。exec()是否用于等待事件继续 更新:timer正在工作,因为我没有在QThread上调用moveToThread(this),这意味着QThread实际上仍然是主线程的一部分。至于QUdpSocket井,我使用轮询函数。因此它不需要处理信号 提示:如果您需要执行init操作,这需要在QThread中执行事件循环,则可以延迟调用moveToThread,直到不再需要信号,这在加载程序时非常实用。您也不需要在构造函数中调用

我没有在代码中调用
exec()
,但是
计时器和
QUdpSocket
工作正常。
exec()
是否用于等待
事件继续

更新:
timer
正在工作,因为我没有在
QThread
上调用
moveToThread(this)
,这意味着
QThread
实际上仍然是
主线程的一部分。至于
QUdpSocket
井,我使用轮询
函数
。因此它不需要处理
信号


提示:如果您需要执行
init
操作,这需要在
QThread
中执行
事件循环
,则可以
延迟调用
moveToThread
,直到不再需要
信号
,这在加载程序时非常实用。您也不需要在构造函数中调用它(例如,您可以在
run()
中调用它),只需将
此QThread
指针复制到一个变量,然后稍后/在其他地方使用该指针进行
调用。

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

各国:

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


如果没有事件循环,可能会发出由GUI线程或包含事件循环的不同线程处理的信号。这意味着线程必须有一个事件循环才能使其插槽有效。根据上面的文档,一些类(如)需要一个运行的事件循环,您必须调用它。其他类,例如,根据所使用的函数,可以在有或没有事件循环的情况下运行。类的文档应该指出它们有什么要求(如果有的话)。

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

分离线程执行循环可防止QApplication循环被非ui相关信号和插槽弄乱,从而延迟。例如,button click的插槽执行,使应用程序“滞后”

注意:通常情况下,您总是子类QThread,有关更多信息,请参阅


编辑:Qt文档错误,请阅读此线程,具体取决于您的程序。以下是一个例子:

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;
}

这个会像你期望的那样工作。OnTransfer将被调用。

我可以认为是在QMainWindow之外的main.cpp ie中实例化QThread时。主要原因是如果在非GUI线程中有多个线程或多个对象。通过这种方式,这些对象的插槽和信号可以在不减慢GUI事件循环的情况下被触发和执行。您可以添加一些代码来解释调用
exec()
的确切位置吗?它是否在QThread的派生构造函数中?如果我从创建QThread的线程调用,它将阻塞线程。你所说的“放置执行循环”是什么意思?你是指调用QThread.exec()还是实际实例化QEvent循环(虽然我不明白为什么我需要这样做,因为QThread提供了一个循环,但从编写答案的方式来看,这让我想到了这一点)事件循环是执行exec()并在class.exec()语句之后阻止代码的任何操作。在本例中,它应该是QThread.exec()。注意:如果你的信号频率很低,你可以放弃线程的想法,因为大部分耗时的Qt命令都是异步的。现在,如果我想让计时器工作,我需要调用exec。但是,如果我需要在run方法中的一个循环中进行处理,那么我需要在每个循环中调用exec一次呢?如果计时器还没有接近完成,我想在计时器超时时尽可能多地进行处理,该怎么办。我在某个地方读到,使用0超时的计时器来管理eventloop是有用的。“在循环中处理”我不明白你的意思。在任何线程中都不应该多次调用exec(),这是一种糟糕的编码风格。如果您真的需要所有的处理能力,但仍然处理信号/插槽:forever{processEvents();//atm我想不起qt函数是如何被称为extrem_cpu_Intensive_task(args);msleep(ms);//给一些毫秒的呼吸时间};注意:这仅适用于单独的QThread派生类,切勿对UI执行此操作,并且仅当您确实需要大量cpu电源和高频率的信号/插槽发射/执行时才执行。QUdpSocket(实际上是QAbstractSocket)中有两个函数,分别称为waitForReadyRead()和waitForBytesWriten()。这表明在不使用信号的情况下进行处理是可能的。当然,如果QThread与gui线程不分离,则不能使用它们,因为它会生成一个双自由异常。在mandlebrot示例中,run()包含一个永久的{}循环。非常感谢。在看到您的帖子之前,我无法完全理解它。
MyThread::MyThread(){
  curl = new Curl(this);
  connect( curl, SIGNAL(OnTransfer(QString)), this, SLOTS(OnTransfer(QString)) );
  start();
}
void MyThread::run(){
  curl->Download("http://google.com");
}