mikrocontroller.net

Forum: PC-Programmierung Threads in QT


Autor: Michael D. (xaero80c51)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michael D. (xaero80c51)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michael D. (xaero80c51)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Mark Brandis (markbrandis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kommunikation zwischen Threads kann man über eine Message Queue 
durchführen.

Autor: zwieblum (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oder shared memory

Autor: Frank Schuessler (fs0001)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michael D. (xaero80c51)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: zwieblum (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michael D. (xaero80c51)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: zwieblum (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.