QThread

QThread提供了一个平台无关的方式来管理线程。
一个QThread对象管理程序里的一个线程。当QThread对象执行run()后它管理的线程开始运行。默认方式,run()函数的执行将调用
exec()函数,开始该线程的事件循环。

你可以使用QObject::moveToThread()来将一个工作对象加入到某个线程中。
class Worker : public QObject
 {
     Q_OBJECT
     QThread workerThread;
 public slots:
     void doWork(const QString &meter) {
         // ...
         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, SIGNAL(finished()), worker, SLOT(deleteLater()));
         connect(this, SIGNAL(operate(QString)), worker, SLOT(doWork(QString)));
         connect(worker,SIGNAL(resultReady(QString)),this, SLOT(h和leResults(QString)));
         workerThread.start();
     }
     ~Controller() {
         workerThread.quit();
         workerThread.wait();
     }
 public slots:
     void h和leResults(const QString &);
 signals:
     void operate(const QString &);
 };

Worker对象的槽函数代码将在另外一个线程中执行。然而,你很方便地将Worker的槽函数连接到任何线程的任何信号。由于队列
连接机制,使得线程之间的信号和槽函数的连接安全。
另外一个让代码在独立的线程中运行的方法是在QThread子类中重新实现run()函数。例如:
class WorkerThread : public QThread
{
    Q_OBJECT
    void run() Q_DECL_OVERRIDE {
        QString result;
        /* 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()那样在线程中开启事件循环。QThread对象存在它被创
建的那个线程中,而不是它所管理的那个线程。一个QThread的槽函数将在创建它的那个线程执行,而不是它所管理的线程。正因
为如此,在QThread的子类中实现新槽函数容易出错,所以不推荐这样。

注意:如果你和某个对象交互,不使用信号和槽的连接方式,比如直接使用函数调用,那么你必须警惕多线程同步的问题。
注意:你不可能改变GUI对象的线程的关系,它们必须在主线程中。

管理线程

当一个QThread管理的线程开始,完成,终止的时候,它将发送一个信号来通知QThread对象,或者QThread对象也可以通过isFinished
(),isRunning()来查询该线程的状态。

QThread对象可以通过调用exit()或则quit()函数来终止它管理的线程。特殊情况下,可以通过调用terminate()函数来强行终止线程的执
行。然而,这样做太危险,不推荐。详细情况请阅读terminate() 和setTerminationEnabled()说明文档。
从Qt 4.8开始,通过连接信号finished()和QObject::deleteLater(),当一个线程运行结束后,自动释放它里面定义的对象。

线程调用wait()函数可以阻断本身的运行,直到其他的线程完成执行(或者一个指定的时间间隔后)。

静态函数currentThreadId() 和currentThread()返回当前运行的线程的标识符。前者返回一个跟平台相关线程ID,后者返回一个QThread
指针。

设置线程的名字(例如在Linux系统中输入ps -L命令可以看到),可以在线程运行之前调用setObjectName() 来设置。如果你不调用它来
设置线程的名字,那么线程将使用线程对象的类名作为名字。注意在windows的release版本中是不可用。

QThread有平台无关的静态睡眠函数: sleep(), msleep(), 和 usleep() ,它们分别实现了秒,毫秒,微秒的精度。

注意:wait()和sleep()是不必要的,Qt是一个事件驱动的架构。finished()信号可以代替wait()函数。QTimer可以代替sleep()函数。
请参看线程相关的类, QThreadStorage, QMutex, QSemaphore, QWaitCondition, M和elbrot Example, Semaphores Example, 和 Wait Conditions
例子

成员变量说明

enum QThread::Priority         这个枚举变量指明了操作系统如何调度新建立的线程。
              值                                                                    含义
QThread::IdlePriority                 0   scheduled only when no other threads are running.
QThread::LowestPriority          1   scheduled less often than LowPriority.
QThread::LowPriority                2   scheduled less often than NormalPriority.
QThread::NormalPriority          3   the default priority of the operating system.
QThread::HighPriority               4    scheduled more often than NormalPriority.
QThread::HighestPriority          5    scheduled more often than HighPriority.
QThread::TimeCriticalPriority  6   scheduled as often as possible.
QThread::InheritPriority             7   use the same priority as the creating thread. This is the default.

成员函数说明

QThread::QThread ( QObject * parent = 0 )
构造一个新的QThread对象来管理一个新线程。它的parent拥有这个QThread。当start()调用,新线程开始执行。
请参考 start().

QThread::~QThread ()
销毁QThread对象
注意:删除一个QThread对象将不会终止它所管理的线程的运行。删除一个运行的线程的QThread对象(就是isFinished()函数返回false)
将可能导致程序崩溃。当收到finished()信号后,删除QThread对象才安全。

QThread * QThread::currentThread () [static]
返回一个管理当前线程的QThread类型的指针。
Qt::HANDLE QThread::currentThreadId () [static]
返回当前执行的线程的线程句柄。
警告:返回的线程句柄应该在内部使用,不应该在其他的程序代码中使用。
警告:在windows,返回的值是当前线程的假句柄。它不能用于数值比较。这个函数的和Win32函数getCurrentThreadId()的返回值都是
一个双字的线程ID号,而不是像Win32函数getCurrentThread()返回一个线程句柄。

int QThread::exec () [protected]
进入事件循环,直到exit()被调用,exit()函数传入的参数作为其返回值.当通过调用quit()来调用exit()的话,返回值为0。
开启事件循环处理必须调用该函数。
请参考 quit() 和 exit().

void QThread::exit ( int returnCode = 0 )
通知线程退出事件循环,并且传入一个code值。
调用该函数后,线程退出事件循环,并从QEventLoop::exec()调用中返回。QEventLoop::exec()返回一个returnCode码。
一般情况,返回码为0意味着调用成功,非0值代表失败。
注意:和c库同名的函数不一样,调用该函数不返回一个值,它仅仅产生一个停止事件。
只有当QThread::exec() 再次调用,才能开启新的事件循环。如果当QThread::exec()开启的事件循环还没有运行的话,立马再次执行
QThread::exec(),它将立即返回。
请参考 quit() 和 QEventLoop.

void QThread::finished () [signal]
当线程执行完毕发出该信号。
请参考 started() 和 terminated().

int QThread::idealThreadCount () [static]
返回该系统上最多能够运行的线程数。无论实际还是逻辑的线程数目都需要访问处理器核心。如果处理器核心不能够被检测,那
么返回-1.

bool QThread::isFinished () const
如果线程已经完成返回true,否则返回false
请参考 isRunning().

bool QThread::isRunning () const
如果线程正在运行返回true,否则返回false。
请参考 isFinished().

void QThread::msleep ( unsigned long msecs ) [static protected]
强制当前线程睡眠msecs 毫秒
请参考 sleep() 和 usleep().

Priority QThread::priority () const
返回当前线程的调度策略,如果线程没有运行,返回InheritPriority.
Qt 4.1开始引进该函数
请参考 Priority, setPriority(), 和 start().

void QThread::quit () [slot]
告诉线程退出事件循环,让exec()返回0(成功)。等同于调用QThread::exit(0)。
如果线程没有事件循环,这个函数什么事也不做。
请参考 exit() 和 QEventLoop.

void QThread::run () [virtual protected]
这是线程的入口处。当调用start()函数后,新产生的线程默认执行该函数。在该函数内,默认是调用exec()函数。
你可以重实现该函数,以完成更好的线程管理。当这个函数执行完毕,就意味着线程执行结束。
请参考start() 和 wait().

void QThread::setPriority ( Priority priority )
该函数为运行的线程设置调度策略。如果这个线程没有执行,那么调用该函数无效并立即返回。当调用start()开启一个线程时候,
该线程会具有一个特定的调度策略。
该调度策略可以是枚举变量QThread::Priority除InheritPriorty外的任何值。
调度参数的效果和操作系统的调度策略有关系。特殊情况,如果操作系统不支持你的调度策略,那么该策略将被忽视。
Qt 4.1开始引进该函数
请参考 Priority, priority(), 和 start().

void QThread::setStackSize ( uint stackSize )
设置线程栈的最大字节数。如果该值大于0,那么stackSize 就是最大的线程栈的值。否则最大的线程栈由操作系统决定。
警告:大多数操作系统对于线程栈的大小都一个范围。如果你设置的线程栈大小不在这个范围的话,那么start()调用将失败。
请参考 stackSize().

void QThread::setTerminationEnabled ( bool enabled = true ) [static protected]
通过enabled参数打开或关闭终止线程的功能。线程必须已经通过QThread对象开始运行。
当enabled为false时,不允许终止。调用QThread::terminate()立即返回并且没有任何效果。线程终止将被延迟直到允许线程终止。
当enabled为true,允许终止。将来调用QThread::terminate()线程将正常终止。如果终止被延迟(比如当不允许终止时调用
QThread::terminate()),那么该函数将使得调用它的线程立即终止,注意该函数无任何返回值。
请参考 terminate().

void QThread::sleep ( unsigned long secs ) [static protected]
强制当前线程睡眠secs 秒
请参考 msleep() 和 usleep().

uint QThread::stackSize () const
如果通过setStackSize()设置过线程栈的话,就返回线程栈的最大值,否则为0
请参考 setStackSize().

void QThread::start ( Priority priority = InheritPriority ) [slot]
通过调用run函数来开始线程的执行。操作系统按照传递来的调度参数来调度该线程。如果线程已运行,该函数什么事都不做。
调度策略参数的效果和操作系统的调度策略有关系。特殊情况,如果操作系统不支持你的调度策略,那么该策略将被忽视。
请参考 run() 和 terminate().

void QThread::started () [signal]
当线程开始执行时,该信号发出。
请参考 finished() 和 terminated().

void QThread::terminate () [slot]
终止线程的执行。线程可能不会立即终止,这取决于操作系统的调度策略。当调用了terminate()后,为了保险,应该侦听terminated
()信号或者使用QThread::wait()来等待线程结束。当线程终止后,所有因等待该线程而休眠的线程将被唤醒。
警告:调用这个函数十分危险,不推荐使用。这样线程可以在其代码的任何位置被终止掉。比如在线程正修改数据的时候终止掉它
。这样就使得线程没有机会清理它自己的资源,比如解开持有的互斥锁。总之,当万不得已时才能使用该函数。
可以通过QThread::setTerminationEnabled()函数设置是否允许线程终止。当不允许终止,调用该函数,终止将被延迟,直到允许终止
。详细情况请参考QThread::setTerminationEnabled()文档说明。
请参考 setTerminationEnabled().

void QThread::terminated () [signal]
当线程终止时,发出该信号。
请参考:started() 和 finished().
void QThread::usleep ( unsigned long usecs ) [static protected]
强制当前线程睡眠usecs 微秒
请参考 sleep() 和 msleep().

bool QThread::wait ( unsigned long time = ULONG_MAX )
阻断调用它的线程运行,直到下面的情况的一种发生:
   当QThread所管理的线程执行结束(当执行run函数返回)。如果线程已经完成这个函数将返回真。如果这个线程还没开始也返回真
   当设定的超时时间后。当使用默认时间ULONG_MAX,wait()等待不会超时返回(要求线程能够从run()函数返回),当超时时间到
,这个函数返回假
在POSIX 线程库中提供的pthread_join()函数和它具有相同的功能。
请参考 sleep() 和 terminate().

void QThread::yieldCurrentThread () [static]
抑制当前线程的执行,使另外可以运行的线程执行。操作系统将决定哪个线程将被转换执行。

QThreadQt 框架中的一个模块,用于处理线程并发。它提供了一种在主线程外执行耗时任务的方式,避免阻塞 GUI 线程,保证了界面的响应速度。关于 QThread 的登录过程,通常包括以下几个步骤: 1. 创建 QThread 对象:在需要异步运行的任务函数前创建一个新的 QThread 实例。 ```cpp QThread *thread = new QThread(); ``` 2. 定义 worker 函数:这是要在新线程上运行的实际任务,这里假设是一个模拟登录操作的函数。 ```cpp void loginWorker() { // 执行登录逻辑,如网络请求、数据库查询等 } ``` 3. 将 worker 函数绑定到线程:通过 moveToThread 方法将 worker 函数关联到 QThread 上。 ```cpp loginWorker.moveToThread(thread); ``` 4. 连接信号和槽:worker 函数结束后,需要通知主线程任务完成,这通常通过 emit signal 来实现。在 worker 函数中添加 emit finished() 或者 emit error(errorString),然后在主线程上设置一个槽函数接收这个信号。 ```cpp QObject::connect(thread, &QThread::finished, []() { /* 主线程处理登录结果 */ }); ``` 5. 启动新线程:调用 start() 方法启动 QThread,并开始执行 worker 函数。 ```cpp thread.start(); ``` 6. 登出或取消操作:如果需要在某个时刻停止线程,可以调用 quit() 方法,线程会在执行完当前任务后自动退出。 注意,QThread 登录过程中应尽量避免直接修改 UI 元素,因为它们只应在主线程中更新。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值