非AI生成,觉得有用,就请您帮忙点赞转发收藏吧,您的鼓励是我创作的动力,多谢看官。
一、connect的完整函数签名
bool connect(const QObject *sender, const char *signal,
const QObject *receiver, const char *method,
Qt::ConnectionType type = Qt::AutoConnection);
参数解释:
sender:发送信号的对象指针。
signal:指向发送对象信号的指针。信号的名称必须以 signals: 开头,例如 SIGNAL(valueChanged(int)) 或使用新的语法 &MyClass::valueChanged(推荐使用C++11或更高版本的C++编译器)。
receiver:接收信号的对象指针。
method:指向接收对象槽的指针。槽的名称必须以 slots: 开头,例如 SLOT(onValueChanged(int)) 或使用新的语法 &MyClass::onValueChanged(推荐使用C++11或更高版本的C++编译器)。
type:连接类型,默认为 Qt::AutoConnection,表示自动选择合适的连接类型(例如,根据线程选择是自动还是直接连接)。其他类型包括 Qt::DirectConnection, Qt::QueuedConnection, Qt::AutoConnection, Qt::BlockingQueuedConnection。
二、如何设置连接类型
在绝大多数常规场景下,使用默认的Qt::AutoConnection 是最优选择,它会根据信号发送者与接收者的线程亲和性(Thread Affinity)自动选择DirectConnection或QueuedConnection。
使用
AutoConnection连接:sender->thread() == receiver->thread():使用
DirectConnectionsender->thread() != receiver->thread():使用
QueuedConnection
三、receiver对槽函数的影响
receiver决定了槽函数的执行线程,槽函数将在receiver->thread()对应的线程中执行。
receiver也影响连接的生命周期,还会影响槽函数执行的安全性。
| 维度 | 带 receiver的connect | 不带receiver的connect |
|---|---|---|
| 生命周期管理 | context销毁时自动断开连接 | 仅sender销毁时断开,否则需手动管理 |
| 执行线程 | 由context->thread() | 与信号发射线程一致(默认) |
| 安全性 | 高(避免悬垂,线程可控) | 较低(可能访问已销毁对象或跨线程不安全) |
| 典型场景 | 类内 lambda 槽(捕获this)、UI 操作 | 无状态 functor、简单逻辑 |
四、type对调用方式的影响
type决定是同步调用,还是异步调用或异步阻塞调用。
注意:就算sender和receiver在同一个线程,也可以显示指定使用QueuedConnection连接方式。
使用Qt::QueuedConnection时,信号发射线程会在发射点完成参数拷贝,并将封装了槽调用信息的QMetaCallEvent投递至接收者对象所关联的线程事件队列;槽函数仅在接收者线程的事件循环执行事件分发时被调用。
五、一个错误的示例
connect(m_workerThread,&QThread::started,this,[=](){ //如果Start函数有阻塞逻辑,例如QWaitCondition::wait或sleep,UI主线程也将卡住不响应 m_worker->Start(); });上面这样编码为什么会阻塞UI线程呢?
receiver是this,决定了槽函数会在当前线程(UI主线程)执行。
正确使用方式:
connect(m_workerThread,&QThread::started,m_worker,[=](){
//就算Start函数有阻塞逻辑,例如QWaitCondition::wait或sleep,UI主线程也不会受影响,因为槽函数是在子线程执行的
m_worker->Start();//其他逻辑
});
如果没有其他逻辑,更简洁的做法:
connect(m_workerThread,&QThread::started,m_worker,&Worker::Start);
六、总结
会用connect函数和用好connect函数还是不一样的,深刻理解它的几个参数对槽函数执行线程和调用方式的影响,这些都需要我们在平时的工作中不断去总结,有助于编程思维的进化,也能让我们编写出更加健壮的Qt程序。
七、参考链接
QT 中的元对象系统(六):connect函数详解