【发布时间】:2017-08-30 15:45:45
【问题描述】:
我正在编写一个包装QUdpSocket的网络库:
QAbstractSocket *UdpNetworkStreamer::addConnection()
{
QUdpSocket *udpSocket = new QUdpSocket(this);
udpSocket->bind(connection.port, QUdpSocket::ShareAddress);
bool ret = udpSocket->joinMulticastGroup(QHostAddress(connection.ip));
connect(udpSocket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::QueuedConnection);
return udpSocket;
}
- 创建一个新的
QUdpSocket。 - 连接到其
readyRead信号。 - 在引发
readyRead时调用readDatagram。
当我使用 Qt GUI 应用程序中的库时,一切正常。
当另一个用户包含在 Qt GUI 应用程序之外使用的库时,问题就开始了。
他调用addConnection(创建套接字并调用readyRead上的connect)
调用addConnection的线程不是Qt。
addConnection 似乎成功结束,但从未发出 readyRead。
调用 read(即使没有发出 readyRead)会导致数据报读取成功。
无效的修复:
-
将 UDP 套接字线程移动到 this->线程
QUdpSocket *udpSocket = new QUdpSocket(); udpSocket->moveToThread(this->thread()); udpSocket->setParent(this); -
我试图通过调用来模拟问题:void
MainWindow::on__btnOpenMulticastReceiver_clicked() { QFuture<void> future = QtConcurrent::run(this, &MainWindow::CreateMulticastConnection, testHandle); }这也导致了与用户使用我的库时相同的症状,这意味着
readyRead没有发出。 QSignalSpy- 我在readyRead信号上激活了一个间谍;尽管我可以直接从套接字读取数据,但计数器一直为零。当使用套接字在主线程上初始化时,间谍给出了有效的结果(即进展)。
我的问题:
- 我错过了什么和做错了什么?
- 发出
readyRead的最简单方法是什么,即使它不是在主 GUI 线程上创建的 - 我找不到任何适用于没有 GUI 或外部 Qt 线程的示例。
【问题讨论】:
-
用户创建
QUdpSocket的线程是否有活动的事件循环?将连接类型更改为Qt::DirectConnection(只是通过快速测试)会发生什么? -
@G.M.试图使用直接连接它没有帮助。创建 udpsocket 的线程没有事件循环,它不是 qt 线程。
-
如果
UdpNetworkStreamer所在的线程没有事件循环,那么队列中的信号永远无法传递给它。我怀疑readyRead信号 is 正在发出,但结果事件位于事件队列中,永远不会被处理。 -
我明白你在说什么,但信号间谍计数器不会至少更新一次吗?它仍然为零...
-
我很确定你需要一个事件循环来发射
readyRead。如果没有触发它的事件,它会发出什么?
标签: c++ multithreading qt sockets qudpsocket