Discuz! Board

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2324|回复: 0
打印 上一主题 下一主题

Qt之线程(QThread)

[复制链接]

1272

主题

2067

帖子

7962

积分

认证用户组

Rank: 5Rank: 5

积分
7962
跳转到指定楼层
楼主
发表于 2018-2-25 15:25:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 Qter 于 2020-12-3 17:15 编辑

  QThread类提供了一个平台无关的方式来管理线程。
  一个QThread对象在程序控制中管理一个线程。线程在run()中开始执行。默认情况下,run()通过调用exec()启动事件循环并在线程里运行一个Qt的事件循环。
  可以使用worker-object通过QObject::moveToThread将它们移动到线程。
  1. class Worker : public QObject
  2. {
  3.     Q_OBJECT

  4. public slots:
  5.     void doWork(const QString ¶meter) {
  6.         // ...
  7.         emit resultReady(result);
  8.     }

  9. signals:
  10.     void resultReady(const QString &result);
  11. };

  12. class Controller : public QObject
  13. {
  14.     Q_OBJECT

  15.     QThread workerThread;

  16. public:
  17.     Controller() {
  18.         Worker *worker = new Worker;
  19.         worker->moveToThread(&workerThread);
  20.         connect(workerThread, &QThread::finished, worker, &QObject::deleteLater);
  21.         connect(this, &Controller::operate, worker, &Worker::doWork);
  22.         connect(worker, &Worker::resultReady, this, &Controller::handleResults);
  23.         workerThread.start();
  24.     }
  25.     ~Controller() {
  26.         workerThread.quit();
  27.         workerThread.wait();
  28.     }

  29. public slots:
  30.     void handleResults(const QString &);

  31. signals:
  32.     void operate(const QString &);
  33. };
复制代码
Worker槽中的代码将在一个单独的线程中执行,然而,可以将(来自任何对象、在任何线程中)任何信号与该槽自由地连接,在不同的线程里连接信号和槽也是安全的,这要归功于一个叫排队的连接机制(queued connections)。     另一种使代码运行在一个单独的线程中的方法,是子类化QThread中并重新实现的run()。例如:
  1. class WorkerThread : public QThread
  2. {
  3.     Q_OBJECT

  4.     void run() Q_DECL_OVERRIDE {
  5.         QString result;
  6.         emit resultReady(result);
  7.     }

  8. signals:
  9.     void resultReady(const QString &s);
  10. };

  11. void MyObject::startWorkInAThread()
  12. {
  13.     WorkerThread *workerThread = new WorkerThread(this);
  14.     connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults);
  15.     connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);
  16.     workerThread->start();
  17. }
复制代码

上面的例子中,在run()返回后线程就会退出,在线程中将不会有任何的事件循环运行除非调用exec()。    注意一个线程实例位于实例化它的旧线程中,而非调用run()的新线程中,这意味着所有线程的排队槽将在旧线程中执行。因此,开发人员希望在新线程调用槽必须使用worker-object方法,新槽不应直接在子类化QThread中来实现。    当子类化QThread时,请记住,构造函数在旧线程中执行,然而run()在新线程中执行。如果一个成员变量的访问来自两个函数,然后从两个不同的线程访问变量,需要检查这样做是否安全。     注:用在不同的线程中的对象进行交互时必须小心。详见同步线程(Synchronizing Threads)。
管理线程    QThread会通知你触发了一个信号当线程started()finished()时,或者使用isFinished()isRunning()来查询线程的状态。    可以通过调用exit()quit()来停止线程。在极端情况下,你可能要强行terminate()一个执行线程。但是,这样做是危险的。请阅读文档查看terminate()setTerminationEnabled()的详细信息。    从Qt4.8起,可以释放运行刚刚结束的线程对象,通过连接finished()信号到QObject::deleteLater()。使用wait()来阻塞调用的线程,直到其他线程执行完毕(或者直到指定的时间过去)。    QThread中还提供了静态的、平台独立的休眠功能:sleep()msleep()usleep()允许秒,毫秒和微秒来区分,这些函数在Qt5.0中被设为public。    注意:一般情况下,wait()sleep()函数应该不需要,因为Qt是一个事件驱动型框架。而不是wait(),关心监听信号finished()。取代sleep(),可以考虑使用QTimer。    静态函数currentThreadId()currentThread()返回标识当前正在执行的线程。前者返回该线程的平台特定的ID,后者返回一个线程指针。    要设置线程的名称,可以在启动线程之前调用setObjectName()。如果不调用setObjectName(),线程的名称将是线程对象的运行时类型(上例中“WorkerThread”,因为这是QThread子类的类名)。请注意,基于Windows的构建版本目前不可用。

http://blog.sina.com.cn/s/blog_a6fb6cc90101hohu.html

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|firemail ( 粤ICP备15085507号-1 )

GMT+8, 2024-11-25 22:47 , Processed in 0.057715 second(s), 20 queries .

Powered by Discuz! X3

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表