问题描述
在项目中需要打开麦克风并将麦克风的数据用WebSocket送到讯飞上进行识别,很自然的新建一个类继承QObject
,然后定义一个QWebSocket
的 成员变量,然后在这个类的构造函数里示例化这个QWebSocket
,最后moveToThread
。
但是当QWebSocket
收到消息却报QSocketNotifier: Socket notifiers cannot be enabled or disabled from another threa
.
尝试将QWebSocket
的实例化放到moveToThread
后,发现还是报错。
原因
查阅资料发现和继承QThread
一样,这个类是在主线程上实例化的,所以是和主类在同一个线程。moveToThread
只是改变了此对象及其子类的线程关联关系(描述不太准确),当该线程启动的时候,对应的方法才是在这个线程中运行(继承QThread
则是在run方法),但是其他方法依旧还是在主类同一个线程。
回到问题,在线程启动后,QWebSocket
对象是在这个线程中接收消息,但是这个对象是在主线程创建的。在Qt中是不可以在不同的线程中操纵QWebSocket
的.(又或者说创建QSocketNotifier
和使用QSocketNotifier
不在同一个线程是不允许,但是没找到官方文档说这样不允许,而且也没找到QSocketNotifier
和QWebSocket
的关系 待深入理解)
https://stackoverflow.com/questions/47449312/qobject-cannot-create-children-for-a-parent-that-is-in-a-different-thread
https://stackoverflow.com/questions/3268073/qobject-cannot-create-children-for-a-parent-that-is-in-a-different-thread
https://stackoverflow.com/questions/36065240/using-qtcpsockets-through-different-threads
解决
在新建类的构造函数中将QWebSocket
对象初始化为nullptr, 然后在对应的槽函数(QThread的是run函数)中实例化
/*---------------------------------------MainWindow.cpp-------------------------------------------------------------*/
connect(m_thread, &QThread::started, m_worker, &Worker::run);
/*------------------------------------Worker.cpp----------------------------------------------------------------------*/
Worker::Worker() : m_websocket(nullptr)
{
}
void Worker::run()
{
if (m_websocket == nullptr)
{
m_websocket = new QWebSocket();
connect(m_websocket, &QWebSocket::connected, this, [this](){
......
}
}
}