Qt signal-slot connect 函数中connection type设置引发的问题

    QThread *ptr=new QThread();
    Worker *pwk=new Worker();
    ptr->setObjectName("Worker thread");
    pwk->moveToThread(ptr);
    QObject::connect(ptr,&QThread::started,pwk,&Worker::run);
    QObject::connect(pwk,&Worker::finished,ptr,[ptr](){
                    qInfo()<<"get finished signal to quit";
                    ptr->quit();});
    ptr->start();
    if(!ptr->wait(5000))
    {
        qInfo()<<ptr<<"is still running:"<<ptr->isRunning();
    }
    qInfo()<<"exit from"<<Q_FUNC_INFO;

Worker是自定义的QObject子类,它有signal finished。上面的代码在main thread中运行,发现ptr的started signal可以传递给pwk的run函数,但是在ptr->wait(5000)的5秒钟内,pwk的finished signal不能传给ptr.
后来偶然发现增加connection type设定:

QObject::connect(pwk,&Worker::finished,ptr,[ptr](){
                    qInfo()<<"get finished signal to quit";
                    ptr->quit();},Qt::DirectConnection);

解决了该问题。后面查找资料,发现原因在于connection type如果没有明确在connect中指定,则缺省为autoconnection。那么Qt如果检测到signal发射方和接收方是在同一个thread,就会使用DirectConnection,如果不是,就会使用QueuedConnection。这里面pwk被move到ptr中,所以它的thread affinity,即pwk->thread()的返回是ptr。但是这不表明pwk和ptr是在一个thread中。ptr因为在main thread中创建,所以ptr->thread()返回是main thread. 因此,如不指定connection type, Qt将采用QueuedConnection,即把signal发到main thread的event loop中。而此时main thread被block在 ptr->wait(5000)中,因此event loop无法接收到该信号。只有当从wait中返回,main thread才能进入event loop循环,接收signal并调用ptr->quit()。

总结一下:

1. connect函数里,如果不指定connection type,默认为autoconnection,如果发射方和接收方在一个thread里,则采用DirectConnection, 即直接调用接收方的函数。而如果不在一个thread里,则发送信号给接收thread的event loop,由它来处理调用接收方的函数。

2. 是否在一个thread里取决于该object的thread affinity,即thread()返回值。一般而言,一个QObject在哪个线程创建,它的affinity就是这个线程,除非调用moveToThread函数把其调到另一个线程,这种情况下,它的thread affinity就变成了函数中的参数。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值