当前位置 博文首页 > Allen Roson:QT QThread

    Allen Roson:QT QThread

    作者:[db:作者] 时间:2021-06-22 21:12

    QThread类提供了一种独立于平台的方式来管理线程。
    A.QThreads开始在run()中执行。默认情况下,run()通过调用exec()启动事件循环,并在线程内运行Qt事件循环。
    您可以通过使用QObject::moveToThread()将辅助对象移动到线程来使用它们。

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

    Worker槽内的代码将在一个单独的线程中执行。但是,你可以自由地将Worker的插槽连接到任何线程中的任何对象的任何信号。由于一种称为排队连接的机制,跨不同线程连接信号和插槽是安全的。另一种让代码在单独的线程中运行的方法是子类化QThread并重新实现run()。例如:

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

    ?

    在该示例中,线程将在run函数返回后退出。除非调用exec(),否则线程中不会运行任何事件循环。
    A.SA.新插槽不应直接实现到子类QThread中。
    在对QThread进行子类化时,请记住构造函数在旧线程中执行,而run()在新线程中执行。A.检查这样做是否安全。
    注意:在跨不同线程与对象交互时必须小心。有关详细信息,请参见同步线程。

    ?

    管理线程
    当线程started()和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是一个事件驱动的框架。与其等待(),不如考虑监听finished()信号。与其使用sleep()函数,不如考虑使用QTimer。
    静态函数currentThreadId()和currentThread()返回当前执行线程的标识符。前者返回线程的平台特定ID;后者返回一个QThread指针。
    要选择将给您的线程提供的名称(例如,由Linux上的ps -L命令标识),您可以在启动线程之前调用setObjectName()。如果你不调用setObjectName(),给你的线程的名字将是你的线程对象的运行时类型的类名(例如,“RenderThread”在Mandelbrot例子的情况下,因为这是QThread子类的名字)。请注意,这目前在Windows上的发布版本中是不可用的。
    请参见Qt中的线程支持、QThreadStorage、同步线程、Mandelbrot示例、Semaphores示例和等待条件示例。

    ?

    成员类型说明

    enum QThread:优先级

    此枚举类型指示操作系统应该如何调度新创建的线程。

    常量值

    数值

    描述

    QThread::IdlePriority

    0

    仅在没有其他线程运行时调度。

    QThread::LowestPriority

    1

    设定比QThread::LowPriority更低的优先级。?

    QThread::LowPriority

    2

    设定比QThread::NormalPriority更低的优先级。

    QThread::NormalPriority

    3

    操作系统的默认优先级。 ?

    QThread::HighPriority

    4

    设定比QThread::NormalPriority更高的优先级。?

    QThread::HighestPriority

    5

    设定比QThread::HighPriority更高的优先级。

    QThread::TimeCriticalPriority

    6

    尽可能提升优先级。

    QThread::InheritPriority

    7

    使用与创建线程相同的优先级。?这是默认值。

    ?

    ?

    下一篇:没有了