QUdpSocket und QThread!

Alles rund um die Programmierung mit Qt
Antworten
gast23
Beiträge: 103
Registriert: 11. August 2010 10:43

QUdpSocket und QThread!

Beitrag 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
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag 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
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag 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...)
gast23
Beiträge: 103
Registriert: 11. August 2010 10:43

Beitrag 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);
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Der Socket wurde doch innerhalb des Threads erstellt - was soll das also nochmal??? Lesen!
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
gast23
Beiträge: 103
Registriert: 11. August 2010 10:43

Beitrag von gast23 »

Dachte ich auch aber du hast dich so merkwürdig ausgedrückt...

Ist mein Aufbau nun ok soweit?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag 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.
gast23
Beiträge: 103
Registriert: 11. August 2010 10:43

Beitrag 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]
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag 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.
gast23
Beiträge: 103
Registriert: 11. August 2010 10:43

Beitrag 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...
gast23
Beiträge: 103
Registriert: 11. August 2010 10:43

Beitrag von gast23 »

super... meine qt version ist nicht 4.6 => QThread ist noch abstract...
Antworten