QT中QObject和函数所处的线程分析
- QObject所处的线程:默认是初始化该对象的线程,可通过
moveTo()
改变其所处线程。 - 函数所处的线程:默认是调用该函数的线程。
- 对象和其成员函数可能处于不同线程:全局变量对象在一个线程初始化,在另一个线程调用其成员函数。
QT中槽函数所处的线程分析
connect(
QObjectClass *sender, SignalMethod signal,
QObjectClass2 *receiver, SlotMethod slot,
Qt::ConnectionType type = Qt::AutoConnection);
如上QObject和其成员函数可能处于不同线程,因此最复杂的情况下connect中需要考虑的线程有四个:
- 信号发送者sender所属的线程A。
- 发送信号的线程B。
- 接收信号者receiver所属的线程C。
- 处理信号的槽函数所处的线程D。
在调用connect时线程A、B、C已经确定,线程D根据connect的第五个参数来确定:
- 自动连接(
Qt::AutoConnection
):这是默认的连接方式。- 当A=C时连接会自动成为直接连接(
Qt::DirectConnection
)。 - 当A≠C时连接会自动变成队列连接(
Qt::QueuedConnection
)。
- 当A=C时连接会自动成为直接连接(
- 直接连接(
Qt::DirectConnection
):信号会在发出信号的函数所在的线程中立即被处理,槽函数的执行线程与发出信号的函数的线程相同,即D=B。在B≠C时这样做会有风险,因为槽函数可能会调用receiver的成员,这些成员和receiver处于同一线程C,这些成员不一定支持多线程操作。 - 队列连接(
Qt::QueuedConnection
):信号会被排队到接收者(槽函数所属对象)所在的线程的事件队列中。当接收者线程的事件循环处理到该信号时,才会调用槽函数。即D=C,线程B会继续执行,当轮询到线程C时才会执行槽函数。 - 阻塞队列连接(
Qt::BlockingQueuedConnection
):与队列连接类似,信号会被发送到接收者所在线程的事件队列中。但是,发出信号的线程会阻塞,直到接收者线程处理完该信号。信号处理是在接收者对象所在的线程中进行。即D=C,线程B会阻塞,系统会立刻跳到线程C并执行槽函数。