[英]How to properly create QUdpSocket on non-gui thread ? Readyread not emitted
I'm writing a network library that wraps the QUdpSocket
: 我正在写一个包装
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
. QUdpSocket
。 readyRead
signal. readyRead
信号。 readDatagram
when readyRead
is raised. readDatagram
readyRead
时,调用readDatagram
。 All is working fine when I use the library from a Qt GUI application. 当我从Qt GUI应用程序使用库时,一切工作正常。
The problem starts when another user includes the library used outside of a Qt GUI application. 当另一个用户包括在Qt GUI应用程序外部使用的库时,问题开始。
He calls the addConnection
(which creates the socket and calls connect on the readyRead
) 他调用
addConnection
(它创建套接字并在readyRead
上调用connect)
The thread on which the addConnection
is called is non-Qt. 调用
addConnection
的线程是非Qt。
The addConnection
seems to end successfully but the readyRead
is never emitted. addConnection
似乎已成功结束,但从来没有发出readyRead
。
Calling read (even though no readyRead
was emitted) leads to a successful datagram read. 调用读取(即使未发出
readyRead
)也会导致成功读取数据报。
Fixes that did not work : 无效的修复:
moving the the UDP socket thread to the this->thread 将UDP套接字线程移动到this-> thread
QUdpSocket *udpSocket = new QUdpSocket(); udpSocket->moveToThread(this->thread()); udpSocket->setParent(this);
I tried to simulate the problem by calling:void 我试图通过调用以下方法模拟该问题:
MainWindow::on__btnOpenMulticastReceiver_clicked() { QFuture<void> future = QtConcurrent::run(this, &MainWindow::CreateMulticastConnection, testHandle); }
This also led to same symptoms as the one the user had with my library, meaning the readyRead
wasn't emitted. 这也导致了与用户使用我的库时出现的症状相同的现象,这意味着没有发出
readyRead
。
QSignalSpy
- I've activated a spy on the readyRead
signal; QSignalSpy
我已经激活了readyRead
信号上的间谍; the counter kept on being zero although I could read data directly from the socket. 尽管我可以直接从套接字读取数据,但计数器始终保持为零。 The spy gave valid results (ie progressed) when used the socket was initialized on the main thread.
当使用套接字在主线程上初始化时,间谍给出了有效的结果(即已执行)。
readyRead
emitted even though it is not created on the main GUI thread - I couldn't find any sample that works with no GUI or outside Qt threads. readyRead
,最简单的方法是什么-我找不到任何没有GUI或外部Qt线程的示例。 My guess is that you need to add Q_OBJECT
macro to the beginning of the class from where you need to emit the signal. 我的猜测是,您需要在需要从那里发出信号的类的开头添加
Q_OBJECT
宏。 Unless you do this, the signal-slot mechanism will not function properly. 除非您这样做,否则信号插槽机制将无法正常运行。
I ended up solving the problem this way : 我最终以这种方式解决了这个问题:
void MainWindow::OpenConnection()
{
QThread *t = new QThread();
t->start();
SocketWrapper *w= new SocketWrapper();
w->moveToThread(t);
w->metaObject()->invokeMethod(w, "CreateSocket", Qt::QueuedConnection);
}
You must call invokeMethod()
with the thread the socket wrapper was movedTo()
upon creation of the socket, so that the thread that creates the socket will have a running event loop. 必须在创建套接字时使用套接字包装程序被
movedTo()
到的线程调用invokeMethod()
,以便创建套接字的线程将具有运行中的事件循环。
In addition to that, the CreateSocket()
needs to be a slot in the SocketWrapper
, something like that : 除此之外,
CreateSocket()
必须是SocketWrapper
一个插槽,类似这样:
class SocketWrapper : public QObject
{
Q_OBJECT
public:
explicit SocketWrapper(QObject *parent = 0);
signals:
public slots:
void readyRead();
void CreateSocket();
private:
QUdpSocket *_socket;
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.