Seite 1 von 1

QUdpSocket und QThread!

Verfasst: 11. August 2010 11:23
von gast23
Hi there,

ich möchte immer mit einem udp server verbunden sein jedoch sollte meine gui nicht blockieren...

aus diesem grund habe ich den udp socket in einem thread ausgelagert...

der thread soll neben den lesen und verarbeiten der daten auch später noch signals verschicken (wurde noch nicht implementiert...)

der code funktioniert jedoch möchte ich wissen ob dieses design richtig ist...

Code: Alles auswählen


#include "uthread.h"

#include <iostream>

UThread::UThread(QObject* parent) : QThread(parent)

{

}

void UThread::run() {

    //Setup

    socket = new QUdpSocket();

    socket->bind(QHostAddress::LocalHost, 2323);

    QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(readData()), Qt::DirectConnection);

    exec();

}

void UThread::readData() {

    while(socket->hasPendingDatagrams()) {

        QByteArray datagram;

        datagram.resize(socket->pendingDatagramSize());

        QHostAddress sender;

        quint16 port;

        socket->readDatagram(datagram.data(), datagram.size(), &sender, &port);

        parse(datagram);

    }

}

void UThread::parse(QByteArray data) {

    QString q(data);

    std::cout << q.toStdString() << std::endl;

}


Zu beginn der entwicklung hatte ich folgenden fehler "QObject: Cannot create children for a parent that is in a different thread. " und es wurde immer nur ein datagram gelesen...

Ich habe bei der slot connection folgendes verändert und danach lief alles: (DirectConnection hinzugefügt).

Code: Alles auswählen


QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(readData()), Qt::DirectConnection);

Bin ich auf dem richtigen weg?

vielen Dank

Verfasst: 11. August 2010 18:27
von Christian81
Das Standardproblem. Das QThread-Objekt wurde natürlich im MainThread erzeugt. Eine Connection in der Art

Code: Alles auswählen

QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(readData())); 
Würde die Datenverarbeitung natürlich im MainThread abhandeln. Das ist aber nicht das was Du möchtest. DirectConnection ist auch nicht unbedingt das was man da machen sollte.
Ich benutz immer ein 'QObject::moveToThread(this)' in der ::run() - Methode um auch dasQThread-Object in den neuen Thead zu holen. Den andere Weg hättest Du auch gefunden wenn man die Foren-Suche benutzt hätte :roll:
http://qtforum.de/forum/viewtopic.php?t ... ht=qthread

Verfasst: 11. August 2010 18:37
von franzf
Dir ist klar, dass bei den Sockets das Abholen asynchron abläuft, und eine Verbindung ansich nicht blockiert? Der Thread ist also unnötig. Sollten die angekommenen Daten aufwändig ausgewertet werden, und das im Endeffekt blockieren, dann verschieb doch die Auswertung in den anderen Thread. Aber auch da würde ich es von Datenmenge und Rechenaufwand abhängig machen, denn kein Thread ist besser als ein Thread :P Also: Wenn du es vermeiden kannst verzichte auf den neuen Thread.
(Unterschätze nie die Macht halbwegs aktueller CPUs...)

Verfasst: 12. August 2010 08:56
von gast23
Hi,

danke für die Antworten.

Ich brauche den Thread weil leider alles blockiert :(

Ich erhalte alle 200ms Daten und durch die while schleife blockiert alles...

Der Aufbau ist wie folgt:
Es gibt ein QMainWindow (Wird in der main der app angelegt) und dieses QMainWindow beinhaltet ein QObject welches diesen QThread von oben beinhaltet... Das QObject bekommt signale vom QThread (Daten werden verschickt) und bearbeitet dann diese Daten... Anschließend werden Signale an QMainWindow geschickt...

Die Sache mit den QThreads ist mir immer noch nicht so klar...
In meiner run habe ich nun den socket mit moveToThread dem QThread zu geteilt...

Code: Alles auswählen

socket->moveToThread(this);

Verfasst: 12. August 2010 09:18
von Christian81
Der Socket wurde doch innerhalb des Threads erstellt - was soll das also nochmal??? Lesen!

Verfasst: 12. August 2010 09:37
von gast23
Dachte ich auch aber du hast dich so merkwürdig ausgedrückt...

Ist mein Aufbau nun ok soweit?

Verfasst: 12. August 2010 09:46
von franzf
In dem verlinkten Thread sollte doch (fast) alles erklärt/ausdiskutiert sein.
*) SLOTS werden im Kontext des Threads ausgeführt, in dem das Objekt angelegt wurde.
*) moveToThread() schiebt das Objekt in die eventLoop eines anderen Threads, so dass SLOTS im Kontext des neuen Threads ausgeführt werden.
*) alles, was in run() direkt gemacht wird, läuft in einem separaten Thread ab.

Lies einfach das was in dem anderen Thread steht, incl. dem Blogeintrag samt Kommentaren (da ist ein Link zu einem Beispiel im "right way").

Und ob du jetzt alles richtig machst, kann man ohne Code nicht sagen. Mit Threads kann man viel Blödsinn treiben.

Verfasst: 12. August 2010 10:00
von gast23
Ich fasse kurz zusammen:

Ich lege eine neue QObject Klasse an die den Socket (PeriodicSocket) kram beinhaltet...
In meiner Haupt QObject Klasse die in QMainWindow angelegt wird, lege ich die neue Socket Klasse (PeriodicSocket) an und gleichzeitig einen QThread. Mit moveToThread verschiebe ich PeriodicSocket in den Thread...

Richtig? [/code]

Verfasst: 12. August 2010 10:07
von franzf
gast23 hat geschrieben:Richtig?
Hört sich soweit gut an. Wie schauen deine Connects aus? Vor allem die in Richtung MainThread und zurück sind interessant.

Verfasst: 12. August 2010 10:11
von gast23
Nach diesem Muster würde ich nun gerne in der Socket Klasse signale an das QObject verschicken und dieses verschickt dann wieder etwas ans QMainWindow...

QMainWindow hat QObject welches Datenverarbeitung betreibt und signals von der Socket Klasse empfängt und QObject verschickt signals an QMainWindow...

Verfasst: 12. August 2010 10:37
von gast23
super... meine qt version ist nicht 4.6 => QThread ist noch abstract...