
在之前的章节中,讲解过QT信号槽的连接类型,但是一个信号链接多个槽函数时,槽函数如何调用呢?是同步呢还是异步?如果是同步,那么多个槽函数中存在一个耗时的,其他槽函数会阻塞吗?
关于Qt信号槽的基础介绍和链接类型,请查看文章:某司客户端面试真题——Qt信号槽 槽函数调用方式
槽函数是同步调用还是异步调用,取决于信号与槽的连接类型。分别为:
Qt::DirectConnection:直接调用槽函数,属于同步调用。Qt::QueuedConnection:将槽函数放入接收者对象的事件队列中,属于异步调用。Qt::AutoConnection:当发送者和接收者在同一个线程时使用 Qt::DirectConnection(同步调用);当发送者和接收者不在同一线程时使用Qt::QueuedConnection(异步调用)。Qt::BlockingQueuedConnection:将槽函数放入接收者对象的事件队列中,属于阻塞式异步调用,但会阻塞发送者线程,直到所有槽函数调用完毕。如果一个信号以同步调用方式同时关联多个槽函数时,槽函数会按照链接顺序依次调用,当其中一个耗时比较长时,后续的槽函数会被阻塞,直到所有槽函数执行完毕。
如果以异步调用方式关联多个槽函数时,槽函数依然会依次调用,但是不会阻塞发送者线程,但接收者线程的执行顺序是按照连接顺序依次执行的。
如果以阻塞式异步调用方式关联多个槽函数时,槽函数依然会依次调用,但是会阻塞发送者线程,直到所有槽函数执行完毕为止。
例如,假设有一个信号 signal(),连接了 5 个槽函数 slot1()、slot2()、slot3()、slot4() 和 slot5(),其中 slot3() 是一个耗时的槽函数。当使用同步调用时,槽函数的执行顺序如下:
slot1() 执行。slot2() 执行。slot3() 执行(耗时),此时会阻塞后续槽函数的执行。slot4() 在 slot3() 完成后执行。slot5() 在 slot4() 完成后执行。此时,信号发出的线程会被完全阻塞,直到所有槽函数执行完毕。
例如,假设信号连接了 5 个槽函数,其中 slot3() 是一个耗时的槽函数。在异步调用的情况下,槽函数会被放入事件队列,如下所示:
slot1() 被放入事件队列。slot2() 被放入事件队列。slot3() 被放入事件队列(耗时)。slot4() 被放入事件队列。slot5() 被放入事件队列。在接收者线程中,槽函数会依次执行:
slot1() 执行。slot2() 执行。slot3() 执行(耗时,但不会阻塞信号发出的线程)。slot4() 在 slot3() 完成后执行。slot5() 在 slot4() 完成后执行。这种机制的优势在于,信号发出的线程不会被阻塞,可以继续执行其他任务。只有接收者线程中的后续槽函数会受到耗时槽函数的影响。
Qt 提供了灵活的信号与槽连接方式,使得开发者可以根据不同的需求选择合适的连接类型。