Qt 线程几种使用方法代码实例

Qt 线程的详细介绍和使用


  • QT::QThread类提供了一种独立于平台的方式来管理线程。QThread对象管理程序中的一个控制线程。QThreads开始在run()中执行。默认情况下,run()通过调用exec()启动事件循环,并在线程内部运行Qt事件循环

  • 通过使用QObject::moveToThread()将worker对象移动到线程,可以使用它。线程将在运行函数返回后退出。除非调用exec(),否则线程中不会运行任何事件循环。

 

  • 必须记住,QThread实例位于实例化它的旧线程中,而不是调用run()的新线程中。
  • 这意味着QThread队列中的所有插槽都将在旧线程中执行。
  • 因此,希望在新线程中调用插槽的开发人员必须使用worker-object方法;不应该将新插槽直接实现到子类QThread中。
  • 在子类化QThread时,请记住,构造函数在旧线程中执行,而run()在新线程中执行。
  • 如果从两个函数访问成员变量,则从两个不同的线程访问该变量。检查一下这样做是否安全。
  • 当线程启动()和finished()时,QThread将通过一个信号通知您,或者您可以使用isFinished()和isRunning()来查询线程的状态。
  • 您可以通过调用exit()或quit()来停止线程。在极端情况下,您可能希望强制终止一个正在执行的线程。然而,这样做是危险的,也是令人气馁的。详细信息请阅读terminate()和setTerminationEnabled()的文档。
  • 从Qt 4.8开始,通过将finished()信号连接到QObject::deleteLater,就可以释放位于刚刚结束的线程中的对象
  • 使用wait()来阻塞调用的线程,直到另一个线程完成执行(或者直到指定的时间过去)。
  • QThread还提供静态的、平台无关的睡眠函数:sleep()、msleep()和usleep()分别允许完全秒级、毫秒级和微秒级的分辨率。这些功能在Qt 5.0中公开。
  • 注意:一般来说,wait()和sleep()函数应该是不必要的,因为Qt是一个事件驱动框架。考虑侦听完成的()信号,而不是wait()。不要使用sleep()函数,考虑使用QTimer。
  • 静态函数currentThreadId()和currentThread()返回当前执行线程的标识符。前者返回线程的平台特定ID;后者返回一个QThread指针。
  • 要选择线程的名称(例如,通过Linux上的命令ps -L识别),可以在启动线程之前调用setObjectName()。如果您不调用setObjectName(),给线程的名称将是线程对象的运行时类型的类名(例如,在Mandelbrot示例中,“RenderThread”是QThread子类的名称)。请注意,目前在Windows上的版本中还不能使用这个功能。

一:Qthread成员函数介绍:

  • 共有成员函数
 

QThread(QObject *parent = Q_NULLPTR)

 

~QThread()

QAbstractEventDispatcher *

eventDispatcher() const

返回指向线程的事件调度程序对象的指针。如果线程不存在事件调度程序,则此函数返回0。

void

exit(int returnCode = 0)

告诉线程的事件循环使用返回代码退出。
调用此函数后,线程将离开事件循环并从对QEventLoop::exec()的调用中返回。函数的作用是::exec()返回返回代码。
按照惯例,返回码为0表示成功,任何非零值表示错误。
注意,与同名的C库函数不同,这个函数确实返回给调用者——停止的是事件处理。

bool

isFinished() const

该信号是在相关线程完成执行之前发出的。
当发出此信号时,事件循环已经停止运行。除了延迟删除事件之外,线程中不会处理任何事件。这个信号可以连接到QObject::deleteLater(),以释放线程中的对象

bool

isInterruptionRequested() const

如果在此线程上运行的任务应该停止,则返回true。requestinterrupt()可以请求中断。
此函数可用于使长时间运行的任务干净地可中断。永远不要检查或作用于这个函数返回的值是安全的,但是在长时间运行的函数中定期这样做是明智的。注意不要太频繁地调用它,以保持低开销。

bool

isRunning() const

如果线程正在运行,返回true;否则返回false。

int

loopLevel() const

返回线程的当前事件循环级别。

Priority

priority() const

返回正在运行的线程的优先级。如果线程不运行,该函数返回InheritPriority。

void

requestInterruption()

请求中断线程。该请求是建议性的,由线程上运行的代码决定是否以及如何响应该请求。此函数不会停止线程上运行的任何事件循环,也不会以任何方式终止它。

void

setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)

将线程的事件调度程序设置为eventDispatcher。只有在还没有为线程安装事件分派器的情况下,才有可能做到这一点。也就是说,在使用start()启动线程之前,或者在主线程中,在实例化QCoreApplication之前。此方法拥有对象的所有权。

void

setPriority(Priority priority)

此函数设置正在运行的线程的优先级。如果线程没有运行,这个函数什么也不做,并且立即返回。使用start()启动具有特定优先级的线程。
优先级参数可以是QThread:: priority enum中的任何值,继承性优先级除外。

void

setStackSize(uint stackSize)

将线程的最大堆栈大小设置为堆栈大小。如果堆栈大小大于零,则将最大堆栈大小设置为堆栈大小字节,否则操作系统将自动确定最大堆栈大小。
警告:大多数操作系统对线程堆栈大小设置最小和最大限制。如果堆栈大小超出这些限制,线程将无法启动

uint

stackSize() const

返回线程的最大堆栈大小(如果设置为setStackSize());否则返回0。

bool

wait(unsigned long time = ULONG_MAX)

阻塞线程,直到满足以下任一条件:

与此QThread对象关联的线程已经完成执行(即当它从run()返回时)。如果线程已经完成,这个函数将返回true。如果线程还没有启动,它还返回true。
毫秒的时间已经用完了。如果时间是ULONG_MAX(默认),那么等待将永远不会超时(线程必须从run()返回)。如果等待超时,此函数将返回false。

二:run 方法

  •   QThreads开始在run()中执行。默认情况下,run()通过调用exec()启动事件循环,并在线程内部运行Qt事件循环
QThread
{
class WorkerThread : public QThread
  {
      Q_OBJECT
      void run() override {
          QString result;
          /* ... here is the expensive or blocking operation ... */
          emit resultReady(result);
      }
  signals:
      void resultReady(const QString &s);
  };

  void MyObject::startWorkInAThread()
  {
      WorkerThread *workerThread = new WorkerThread(this);
      connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults);
      connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);
      workerThread->start();
  }

}

三:QObject::moveToThread() 方法

  • 通过使用QObject::moveToThread()将worker对象移动到线程,可以使用它。因此,希望在新线程中调用插槽的开发人员必须使用worker-object方法;不应该将新插槽直接实现到子类QThread中。这种方法;
class Worker : public QObject
  {
      Q_OBJECT

  public slots:
      void doWork(const QString &parameter) {
          QString result;
          /* ... here is the expensive or blocking operation ... */
          emit resultReady(result);
      }

  signals:
      void resultReady(const QString &result);
  };

  class Controller : public QObject
  {
      Q_OBJECT
      QThread workerThread;
  public:
      Controller() {
          Worker *worker = new Worker;
          worker->moveToThread(&workerThread);
          connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
          connect(this, &Controller::operate, worker, &Worker::doWork);
          connect(worker, &Worker::resultReady, this, &Controller::handleResults);
          workerThread.start();
      }
      ~Controller() {
          workerThread.quit();
          workerThread.wait();
      }
  public slots:
      void handleResults(const QString &);
  signals:
      void operate(const QString &);
  };

总结:

具体的一些例子官方已经给出demo:

参见Qt、QThreadStorage、同步线程、Mandelbrot示例、信号量示例和等待条件示例中的线程支持一些实例:
Thread Support in Qt, QThreadStorage, Synchronizing Threads, Mandelbrot Example, Semaphores Example, and Wait Conditions Example.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章