理解不同的连接方式

Qt::AutoConnection
自动连接:(默认值)如果信号在接收者所依附的线程内发射,则等同于直接连接。如果发射信号的线程和接受者所依附的线程不同,则等同于队列连接。

Qt::DirectConnection
直接连接:当信号发射时,槽函数将直接被调用。无论槽函数所属对象在哪个线程,槽函数都在发射信号的线程内执行。

Qt::QueuedConnection
队列连接:当控制权回到接受者所依附线程的事件循环时,槽函数被调用。槽函数在接收者所依附线程执行。也就是说:这种方式既可以在线程内传递消息,也可以跨线程传递消息

Qt::BlockingQueuedConnection
与Qt::QueuedConnection类似,但是会阻塞等到关联的slot都被执行。这里出现了阻塞这个词,说明它是专门用来多线程间传递消息的

怎么理解上面的话呢?我总结起来有如下几个关键点:

  1. 每个线程都有自己的栈空间,每个线程都拥有很多对象。一个QThread对象就代表一个线程,对象必定属于某一个线程。
  2. connect语句的位置不太重要,因为它仅仅是将两个对象关联,重要的就是这个对象的关联关系。
  3. 发射信号的语句执行的线程 与 接受者所生存的线程有关系就影响者代码到底是在哪个线程中执行的问题。
  4. QThread的start信号发射语句所执行的线程即不是调用语句所在的线程,也不是目标线程。可以认为是一个运行在一个临时的次线程空间中。

QThread在次线程中发射start信号,最终创建一个新的线程,新的线程的起点就是run函数,默认就是执行exec处理线程的消息循环。因此,QT使用线程有两种方式,一种是子类化QThread并重写run函数。另外一种是创建一个无父对象的QObject对象,将QObject移动到QThread中,因为没有重写run函数,因此在start后新线程一种在处理消息循环。通过信号槽机制,可以需要的代码放入到新线程中执行。

QtConcurrent

一种不需要关心底层线程,可以自动并行执行的方法。比如,自动并行处理一些数据。一般GUI编程中这个用到的会比较少。

1. QtConcurrent::run
2. QtConcurrent::map
3. QtConcurrent::filter

相关类有:QFuture、QFutureWatcher

线程相关

加锁,事件唤醒主要有如下的类:QMutex, QWaitCondition、QReadLocker、QReadWriteLock、QMutexLocker、QWriteLocker、QSemaphore
QWaitCondition必须与QMutex或者QReadwriteLock一起用