一、问题描述
今天遇到一个问题,我在一个子线程中定义一个信号与槽函数,然后直接连接,最后会报错Socket notifiers cannot be enabled or disabled from another thread
connect(thread_udpSocket,&QUdpSocket::readyRead,this,&Mythread::read_UDPData);
exec();
二、问题解决
这是应为在高版本中QT的run函数限制比较多,基本无法使用信号与槽的方式,在子线程中只有run里面是子线程。别的都是父线程,所以调用其他函数就是夸线程调用了。
解决办法:
1:我是直接在connect函数第五个参数添加一个直连的方式,但是这种方式隐患比较f多,如果测试基本没问题,做产品不行
第五个参数代表槽函数在哪个线程中执行 :
1)自动连接(AutoConnection),默认的连接方式,如果信号与槽,也就是发送者与接受者在同一线程,等同于直接连接;如果发送者与接受者处在不同线程,等同于队列连接。(这个是线程安全的,默认是这个)
2)直接连接(DirectConnection),当信号发射时,槽函数立即直接调用。无论槽函数所属对象在哪个线程,槽函数总在发送者所在线程执行,即槽函数和信号发送者在同一线程(注意这个是不安全的)
3)队列连接(QueuedConnection),当控制权回到接受者所在线程的事件循环时,槽函数被调用。槽函数在接受者所在线程执行,即槽函数与信号接受者在同一线程
4)锁定队列连接(QueuedConnection)
Qt::BlockingQueuedConnection:槽函数的调用时机与Qt::QueuedConnection一致,不过发送完信号后发送者所在线程会阻塞,直到槽函数运行完。接收者和发送者绝对不能在一个线程,否则程序会死锁。在多线程间需要同步的场合可能需要这个。
5)单一连接(UniqueConnection)
Qt::UniqueConnection:这个flag可以通过按位或(|)与以上四个结合在一起使用。当这个flag设置时,当某个信号和槽已经连接时,再进行重复的连接就会失败。也就是避免了重复连接
如果槽函数中有耗时操作,比如说while循环,主线程的信号子线程是不会响应的,除非使用直接连接(DirectConnection),connect(this, &Controller::kill, worker, &Worker::stopWork, Qt::DirectConnection);,此时,槽函数工作于主线程。
(Qt有两种多线程的方法,其中一种是继承QThread的run函数,另外一种是把一个继承于QObject的类转移到一个Thread里。 Qt4.8之前都是使用继承QThread的run这种方法,但是Qt4.8之后,Qt官方建议使用第二种方法。两种方法区别不大,用起来都比较方便,但继承QObject的方法更加灵活。)
2:就是使用movetothead,封装一个类和一个线程绑定,这个我还没用,暂时改参数使用