Forum: PC-Programmierung Threads in QT


von Michael D. (Gast)


Lesenswert?

Hallo Forum,

ich bin ein blutiger Anfänger in C++ und habe fast keine Erfahrung in 
QT.

Im Moment arbeite ich an einem Projekt, welches Daten über die Serielle 
Schnittstelle sendet und wieder einliest - das geht bereits. Weiteres 
sollen die Daten auch auf der Gui ausgegeben werden - was über manuelle 
betätigung über Buttons auch Funktioniert.
Mein Ziel ist es, das senden und empfangen in einer Schleife ausführen 
zu lassen.

Hierfür habe ich im Programm wo SetupUi aufgerufen wird einen Thread 
erzeugt, welcher auch ausgeführt (zZ. while(1) Schleife in der 
run()-Methode) wird. In diesem soll dann das Senden/Empfangen 
stattfinden.

Miniterminal::Miniterminal(QMainWindow *parent) : QMainWindow(parent){

  setupUi(this);
  connect(buttonConnect, SIGNAL(clicked()), this, SLOT(Verbinden()));
  connect(buttonSend, SIGNAL(clicked()), this, SLOT(Senden()));
  a.start(); // Thread
}

Mein eigentliches Problem ist, wie ich die empfangenen Daten vom Thread 
a in das UI bekomme.

Bis jetzt habe ich folgendes Probiert:
Ich habe im Thread die "ui_Miniterminal.h" eingebunden (vom qmake 
erzeugte GUI Header) und lineSenden->setText("Test"); (lineSenden ist 
der Objektname von meinem LineEdit) aufgerufen, was er mir mit der 
Fehlermeldung 'lineSenden undecleared' aber leider verweigert.

Wie kann ich dieses Problem am einfachsten lösen?
Was wäre der sauberste Weg?

Danke im vorraus,
Mike

EDIT:
Entwicklung unter Windows XP, QT 4.5.1/MinGW

von Rolf Magnus (Gast)


Lesenswert?

Wozu brauchst du denn da Threads?

> Hierfür habe ich im Programm wo SetupUi aufgerufen wird einen
> Thread erzeugt, welcher auch ausgeführt (zZ. while(1) Schleife in der
> run()-Methode) wird. In diesem soll dann das Senden/Empfangen
> stattfinden.

So würde dein Programm ständig die CPU zu 100% auslasten.

von Michael D. (Gast)


Lesenswert?

Hallo Rolf,

Den Thread brauche ich da mir eine Schleife im GUI die GUI blockieren 
würde. Zumindest habe ich ausser einem Thread noch keine Lösung 
gefunden.

Das der Thread mit while(1) 100% (in meinem Fall 25% dank Quadcore ;-) ) 
frisst, ist mir durchaus bewusst und kommt später auch wieder raus. 
Geplant ist Daten senden und abholen und dann den Thread für 500ms oder 
so schlafen zu legen. Die while(1) ist im Moment nur drinn um den Thread 
am Leben zu erhalten.

Mein Promlem ist wie ich die Datem aus dem Thread in die GUI bekomme.

Mike

von Rolf Magnus (Gast)


Lesenswert?

Für die serielle Schnittstelle empfehle ich QExtSerialPort. Das ist eine 
Erweiterungsbibliothek zu Qt, die die serielle Schnittstelle als 
QIODevice zur Verfügung stellt. Und statt deiner Schleife könntest du 
auch einfach einen QTimer verwenden. Da muß dann nirgends mehr blockiert 
werden.

von Michael D. (Gast)


Lesenswert?

Hallo Rolf,

das mit dem Timer klingt sehr interessant und würde in diesem Fall den 
selben Zweck erfüllen. Ähnlich wie bei einem uC-Timer halt - insofern 
ich das jetzt richtig interpretiert habe. Werde mich morgen da mal 
reinlesen.

QIODevice klingt auch sehr gut. Ich habe zwar aus Codeteilen aus dem 
Netz schon eine funktionierende Schnittstelle gebastelt, aber möchte 
dennoch viel QT verwenden, da ich das in ein paar Monaten in der Firma 
brauchen werde.

Vielen Dank für die Hinweise und eine schöne Woche,
Mike

von Mark B. (markbrandis)


Lesenswert?

Kommunikation zwischen Threads kann man über eine Message Queue 
durchführen.

von zwieblum (Gast)


Lesenswert?

oder shared memory

von Frank S. (fs0001)


Lesenswert?

Hi Michael,

Signal und Slots ist der standard QT Mechanismus für 
Interprozesskommunikation (u.a. Threads). Prinzipiell hast Du immer ein 
Signal im einem Thread (emitter) und einen (oder mehrere) Slots in 
anderen Threads (receiver) die das Signal empfangen.

Zu Deiner Frage wie man Daten vom einen in den anderen Thread kriegt:
Eben mit Signal/Slots. Signal koennen mehrere Paramter haben (u.a. Deine 
Daten). Du kannst also ein eigenes Signal und einen dazugehörigen Slot 
definieren und Deine Nutzdaten beim emit() übergeben.
Du kannst aber auch global ein Datenhaltungsobjekt erzeugen, dieses über 
einen Mutex schützen und von beiden Threads darauf zugreifen (das waere 
dann so ähnlich wie shared memory). Wie gesagt, da gibts viele viele 
Möglichkeiten.

Fang mal hier an zu lesen:

http://doc.trolltech.com/4.5/signalsandslots.html
danach:
- google: qt thread
- google: qt signal slots direct connection
- google: qt signal slots queued connection


Gruss
Frank

von Rolf Magnus (Gast)


Lesenswert?

> oder shared memory

Hm? Threads haben schon einen gemeinsamen Speicher. Das ist ihr Vorteil 
gegenüber getrennten Prozessen.

> Eben mit Signal/Slots. Signal koennen mehrere Paramter haben (u.a.
> Deine Daten). Du kannst also ein eigenes Signal und einen
> dazugehörigen Slot definieren und Deine Nutzdaten beim emit()
> übergeben.

Wohlgemerkt unterscheidet sich der Signal/Slot-Mechanismus zwischen zwei 
Threads von dem innerhalb eines Threads. Letzterer ist im Prinzip nur 
ein Memberfunktions-Aufruf über einen Zeiger. Bei ersterem werden die 
Daten kopiert und durch die Event-Queue geschleift. Dazu muß man seine 
Klasse erst bei Qt anmelden. Man muß sich halt im Klaren darüber sein, 
daß man nicht ein gemeinsames Objekt hat, auf das beide zugreifen, 
sondern daß bei jedem Signal, das zwischen den Threads gesendet wird, 
die gesamten Daten erst kopiert werden.

von Michael D. (Gast)


Lesenswert?

Hallo,

ich habe mich gestern Abend auseinander gesetzt und mich dann für die 
Signal/Slot Methode entschieden.
Nach ein paar Anlaufschwierigkeiten (QT Newbie halt) hat es dann 
geklappt.

Speziell Rolf und Frank möchte ich nochmals Danke sagen.

Lg,
Mike

von Klaus W. (mfgkw)


Lesenswert?

Noch als Anmerkung:
- in einer Schleife Lesen und Schreiben schadet nichts und lastet
  auch einen Prozessor nicht zu 100% aus, falls das Lesen blockiert,
  solange keine Daten zum Lesen da sind.
  Es ist durchaus üblich, in einem Thread ohne irgendwelche Wartezeiten
  in einer Endlosschleife zu lesen.
  Die nötige Verzögerung kommt automatisch, wenn die Eingabe stockt.

von zwieblum (Gast)


Lesenswert?

> Hm? Threads haben schon einen gemeinsamen Speicher. Das ist ihr Vorteil
> gegenüber getrennten Prozessen.
ja, eben. mit ein bischen hirnschmalz kann man die kommunikation darüber 
abwickeln.

von Michael D. (Gast)


Lesenswert?

Auch wenn man die Kommunikation über einen gemeinsamen Speicher 
durchführen kann, muss man die Daten in den Feldern manuell (oder eben 
Thread ) aktualisieren oder direkt in deren Speicher schreiben, oder?

von zwieblum (Gast)


Lesenswert?

ja. aber qt ist ja angäblich threadsave. ergo kannst du die daten 
schreiben und dann per QApplication::postEvent() der gui mitteilen dass 
sich was getan hat.

von Rolf Magnus (Gast)


Lesenswert?

> ja. aber qt ist ja angäblich threadsave.

Die meisten Klassen in Qt sind threadsave. Das heißt, daß du diese 
Klassen über mehrere Threads hinweg benutzen kannst. Es heißt nicht, daß 
du dich, nur weil du an Qt linkst, auf einmal gar nicht mehr um 
Synchronisation zwischen Threads kümmern mußt. Deine eigenen Typen mußt 
du schon selbst threadsave machen.

von gast (Gast)


Lesenswert?

nur um Missverständnissen vorzubeugen:

Threadsafe heisst nur, dass sich zwei Objekte einer Klasse nicht 
gegenseitig beeinflussen. Wenn man auf ein Objekte einer 
threadsafe-Klasse von zwei Threads gleichzeitig (r/w) Zugreifen möchte, 
kommt man i.d.R. nicht um einen Mutex oder RWLock herum

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.