我正在编写一个包装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
信号。readDatagram
被提出时致电readyRead
。当我使用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
发出$authenticated = Sentinel::getUser()->first_name;
,最简单的方法是什么 - 我找不到任何无GUI或外部Qt线程的样本。 答案 0 :(得分:0)
我的猜测是你需要将Q_OBJECT
宏添加到需要发出信号的类的开头。除非你这样做,否则信号槽机制将无法正常工作。
答案 1 :(得分:0)
我最终以这种方式解决问题:
void MainWindow::OpenConnection()
{
QThread *t = new QThread();
t->start();
SocketWrapper *w= new SocketWrapper();
w->moveToThread(t);
w->metaObject()->invokeMethod(w, "CreateSocket", Qt::QueuedConnection);
}
在创建套接字时,必须使用套接字包装器invokeMethod()
的线程调用movedTo()
,以便创建套接字的线程将具有正在运行的事件循环。
除此之外,CreateSocket()
必须是SocketWrapper
中的一个插槽,类似于:
class SocketWrapper : public QObject
{
Q_OBJECT
public:
explicit SocketWrapper(QObject *parent = 0);
signals:
public slots:
void readyRead();
void CreateSocket();
private:
QUdpSocket *_socket;
};