Как правильно создать QUdpSocket в потоке без GUI? Readyread не испускается

Я пишу сетевую библиотеку, которая оборачивает 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 (который создает сокет и вызывает соединение на readyRead)

Нить, на которой addConnection называется не-Qt.

addConnection кажется, заканчивается успешно, но readyRead никогда не излучается.

Звонить читать (хотя нет readyRead был выпущен) приводит к успешному чтению дейтаграммы.

Исправления, которые не работали:

  1. перемещение потока UDP-сокета в поток this->

    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. Какой самый простой способ иметь readyRead даже если он не создан в основном потоке графического интерфейса — я не смог найти ни одного примера, который бы работал без графического интерфейса или вне потоков Qt.

0

Решение

Я думаю, что вам нужно добавить Q_OBJECT макрос в начало класса, откуда вам нужно испустить сигнал. Если вы не сделаете этого, механизм прорези сигнала не будет работать должным образом.

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;
};
0

По вопросам рекламы [email protected]