Slot eines QThreads aufrufen

Alles rund um die Programmierung mit Qt
Antworten
WeeZer
Beiträge: 19
Registriert: 8. März 2006 16:44
Kontaktdaten:

Slot eines QThreads aufrufen

Beitrag von WeeZer »

Ich benötige einen Thread für eine TCP-Verbindung der mehrere Aufgaben übernimmt, er soll den TCP-Socket verbinden, sich einloggen, Daten holen usw.
Das versuche ich zu realisieren in dem mein QThread für jede Aufgabe einen Slot bekommt (connectToServer(), login(), ...). Damit das so funktioniert, ist natürlich vorausgesetzt das die Slots auch in meinem Thread ausgeführt werden, und nicht in dem Thread von dem ich die Slots aufrufe.

Um das zu testen, habe ich einen QThread mit einem block() Slot erstellt, in dem eine while(true) Schleife gestartet wird. Den Slot verbinde ich mit einem Signal von einem QPushButton mit dem ConnectionType QueuedConnection und erwarte jetzt, das sobald ich den Button klicke, die while schleife in meinem Thread läuft, und meine GUI nicht blockiert wird, sie wird aber blockiert was ich nicht verstehe, denn in der Dokumentation steht:
With queued connections, the slot is invoked when control returns to the event loop of the thread to which the object belongs. The slot is executed in the thread where the receiver object lives.

Code: Alles auswählen

class MyThread : public QThread
{
    Q_OBJECT
public:
    void run();
public slots:
    void block();
};

void MyThread::run()
{
    exec();
}

void MyThread::block()
{
    qDebug("starting to block");
    while(true);
}

Code: Alles auswählen

int main( int argc, char **argv )
{
    QApplication app(argc, argv);

    QPushButton button("push me");
    button.show();
    
    MyThread thread;
    QObject::connect(&button, SIGNAL(clicked()), &thread, SLOT(block()), Qt::QueuedConnection);
    thread.start();
    
    return app.exec();
}
Jetzt stehe ich auf dem Schlauch und weiß nicht was ich falsch mache, ich habe auch schon alle anderen ConnectionType aufprobiert die vorhanden sind, aber bei keinem funktioniert es.
Seht ihr meinen Fehler?
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Nein, ich kann keinen Fehler finden. Und der Code wird auch einwandfrei übersetzt bei mir und läuft, so wie er soll...
WeeZer
Beiträge: 19
Registriert: 8. März 2006 16:44
Kontaktdaten:

Beitrag von WeeZer »

Bei mir wird das Programm auch übersetzt. Nur wird der block() Slot nicht in MyThread ausgeführt, sondern im GUI Thread.
Oder ist das bei dir anders?
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Achso :)

Ich hab mich jetzt selbst mal ein bißchen schlau gemacht. Man muß ein innerhalb des Threads ein QObject erzeugen, dann kann man dessen Slots in diesem Thread laufen lassen...
WeeZer
Beiträge: 19
Registriert: 8. März 2006 16:44
Kontaktdaten:

Beitrag von WeeZer »

Gut, ich bin davon ausgegangen das die Slots von QThread auch in dem Thread ausgeführt werden, dem ist wohl nicht so.
In meinem Beispiel müsste ich jetzt also noch eine Klasse mit dem gewünschten Slot erstellen, und von dieser Klasse in QThread::run() ein Objekt anlegen. Nur wie verbinde ich am saubersten Signale außerhalb des Threads mit dem Slot meines neuen Objekts?

Ich habe es gerade geschafft, indem ich meinem QThread das Signal blocksignal() gegeben habe und es mit dem Slot des Objekts in dem Thread verbunden habe.
Das clicked() Signal von meinem QPushButton habe ich dann mit dem blocksignal() des Threads verbunden.
Das funktioniert soweit, nur gefällt mir diese Lösung nicht.

Wie sieht denn der generelle Aufbau eines QThreads der verschiedene Aufgaben erledigen soll aus, macht man das so, dass man eine Klasse mit den Aufgaben erstellt, und von ihr ein Objekt in dem Thread erzeugt?
nando
Beiträge: 321
Registriert: 28. Oktober 2004 13:16

Beitrag von nando »

Am besten mit einer art proxy signals/slots....

also fuer jeden slot, den du in der QObject klasse die aus der run methode gestartet und somit im thread laeuft aufrufst erstellst du einen slot in the QThread abgeleiteten klasse.
in diesem slot rufst du dann einfach den slot der klasse auf die im thread laufen soll.....
das queued connection duerftetst du dir sparen koennen, da Qt erkennt dass die verbindung ueber thread ebene geht und dann automatisch queued connections nimmt...
fuer signale dann einfach umgekehrt.....


gruss,
nando
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Hab das noch ned gebraucht, weil ich es als overhead empfinde ....

aber, laut Doku, wenn man den QThread mit ner eigenen Loop startet .... also in dem run() vom thread das exec() aufrufst (was du ja machst), dann laeuft die loop in dem Thread ....
und alle slots die per connection mit signalen von ausserhalb des threads verbunden werden, laufen queued, also im thread der auch exec aufegerufen hat.
darfst halt nur die slots ned direkt aufrufen sondern immer nur ueber ne signal/slot connection ...

Ist dem ned so ? Also laut doku muss man kein object im thread erzeugen, sondern der thread muss nur ne eigene eventloop haben.
Welche version habt Ihr ?

Ciao ...
Antworten