1

我正在编写一个包含以下内容的网络库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;
}
  1. 创建一个新的QUdpSocket.
  2. 连接到它的readyRead信号。
  3. readDatagram提出时调用readyRead

当我使用 Qt GUI 应用程序中的库时,一切正常。

当另一个用户包含在 Qt GUI 应用程序之外使用的库时,问题就开始了。

他调用addConnection (创建套接字并调用 connect readyRead

调用的线程addConnection是非 Qt。

addConnection似乎成功结束,但从未readyRead发出。

调用 read(即使没有readyRead发出)会导致成功的数据报读取。

无效的修复:

  1. 将 UDP 套接字线程移动到 this->thread

    QUdpSocket *udpSocket = new QUdpSocket();
    udpSocket->moveToThread(this->thread());
    udpSocket->setParent(this);
    
  2. 我试图通过调用来模拟问题:void

    MainWindow::on__btnOpenMulticastReceiver_clicked()
    {
       QFuture<void> future = QtConcurrent::run(this, 
       &MainWindow::CreateMulticastConnection, testHandle);
    }
    

    这也导致了与用户对我的库的相同症状,这意味着readyRead没有发出。

  3. QSignalSpy- 我已经激活了对readyRead信号的间谍;尽管我可以直接从套接字读取数据,但计数器一直为零。当使用套接字在主线程上初始化时,间谍给出了有效的结果(即进展)。

我的问题:

  1. 我错过了什么,做错了什么?
  2. 即使不是在主 GUI 线程上创建发出的最简单的方法是什么readyRead- 我找不到任何在没有 GUI 或外部 Qt 线程的情况下工作的示例。
4

2 回答 2

2

我最终以这种方式解决了问题:

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;
};
于 2017-04-06T14:49:14.937 回答
0

我的猜测是,您需要将Q_OBJECT宏添加到您需要发出信号的类的开头。除非您这样做,否则信号槽机制将无法正常工作。

于 2017-04-05T07:31:31.773 回答