Lambda 与信号-槽机制
常规信号-槽连接方式
connect(sender, &Sender::mySig, recver, &Recver::mySlot);
替换换成 Lambda 方式
connect(sender, &Sender::mySig, recver, [recver](){ recver->mySlot(); });
注意,这里 connect 函数的第3个填了 recver 指针,确保槽函数在 recver 线程中运行 如果不填第3个参数,则会直接运行于 sender 线程中,如下:
// 这种连接方式,适用于直接调用。千万不要在UI和后台线程之间使用这种连接方式
connect(sender, &Sender::mySig, [recver](){ recver->mySlot(); });
同时要注意,如果 connect 同时指定的 sender 和 recver 指针,则其中任意对象被销毁后,信号自动断开。如果没有指定 recver 指针,则信号不会随着对象销毁而被销毁,有可能造成不确定的问题,使用时需要小心。
后台线程切到UI线程中运行代码
调用槽函数
后台线程调用槽函数可以使用 QMetaObject::invokeMethod
QMetaObject::invokeMethod(obj, "method_name", ...);
这种方式有个局限就是只能调用对象的槽函数
调用 Lambda
QTimer::singleShot(0, [recver]() { recver->mySlot(); });
QTimer::singleShot(0, recver, [recver]() { recver->mySlot(); });
QTimer::singleShot(10, recver, &Recver::mySlot });
效率会稍低一些,但更加灵活。 同样的,如果不指定recver指针,该信号不会随着对象销毁而断开,有可能造成不确定的问题,使用时需要小心。
总结
- 多线程环境下,接收对象决定槽函数在哪个线程中执行
- 若传入接收对象参数,槽函数在接收对象所在的线程中执行;
- 若不传入接收对象参数,槽函数在调用线程中执行。