Anwendung nebenläufig machen mit QThread

Alles rund um die Programmierung mit Qt
Antworten
stefan-tiger
Beiträge: 49
Registriert: 28. März 2006 22:52

Anwendung nebenläufig machen mit QThread

Beitrag von stefan-tiger »

Hallo,

Uch habe hier eine Qt-Anwendung, in der es eine Klasse A gibt, die als Menmber zwei andere Klassen X und Y instanziert.

Klasse X ist mein GUI (QWidget) Klasse Y fasst Funktionen usw. für eine USB-Hardware zusammen.

Jetzt habe ich in der Klasse Y Funktion en, die in einer Schleife was über USB ausgibt. Solange diese ausgeführt wird bleibt die ganze Anwendung "stehen".

Ich möchte erreichen, daß ich in der GUI weiterarbeiten kann und im "Hintergrund" die Ausgabe auf dem USB-Gerät erfolgt.

Ich denke ich muss kann/dazu QThreads benutzen.

Leider weiss ich nicht genau was ich machen muss.

Soll ich einfach Klasse Y von QThread ableiten und das was bisher im Konstruktor stand in die Funtktion run() verfrachten? Ist das alles oder was müsste ich sonst noch tun?
Shadow
Beiträge: 92
Registriert: 27. August 2005 18:15
Wohnort: Iserlohn
Kontaktdaten:

Re: Anwendung nebenläufig machen mit QThread

Beitrag von Shadow »

stefan-tiger hat geschrieben:
[..cut..]

Soll ich einfach Klasse Y von QThread ableiten und das was bisher im Konstruktor stand in die Funtktion run() verfrachten? Ist das alles oder was müsste ich sonst noch tun?
Wie es prinzipiell zu laufen hat:

- Eine Klasse von QThread ableiten und virtuelle Methode "run()" überschreiben.
- In dieser Methode den Code einfügen, den der Thread ausführen soll.
- Die Methode start() erzeugt den neuen Thread aus Systemebene und springt die Methode "run()". an.
- Der Thread wird automatisch beendet, wenn "run()" durchgelaufen ist. Damit ist allerdings nur der vom Betriebssystem verwaltete Thread verschwunden, das QThread-Objekt besteht weiterhin.

Sieh dir mal diesen Thread an.
stefan-tiger
Beiträge: 49
Registriert: 28. März 2006 22:52

Re: Anwendung nebenläufig machen mit QThread

Beitrag von stefan-tiger »

Shadow hat geschrieben:
stefan-tiger hat geschrieben:
[..cut..]

Soll ich einfach Klasse Y von QThread ableiten und das was bisher im Konstruktor stand in die Funtktion run() verfrachten? Ist das alles oder was müsste ich sonst noch tun?
Wie es prinzipiell zu laufen hat:

- Eine Klasse von QThread ableiten und virtuelle Methode "run()" überschreiben.
- In dieser Methode den Code einfügen, den der Thread ausführen soll.
- Die Methode start() erzeugt den neuen Thread aus Systemebene und springt die Methode "run()". an.
- Der Thread wird automatisch beendet, wenn "run()" durchgelaufen ist. Damit ist allerdings nur der vom Betriebssystem verwaltete Thread verschwunden, das QThread-Objekt besteht weiterhin.

Sieh dir mal diesen Thread an.
Ich habs halbwegs hinbekommen.

Mein Problem: Ich möchte eine ganze Instanz einer Klasse nebenläufig machen.

So wie ich das sehe, kann ich mit einer Klasse QThread immer nur eine einzige Funktion nebenläufig aufrufen, nämlich run().

Meine Klasse hat aber schonmal 3 Funktionen nach dem Schema: read(), write(), test()

Wenn ich jetzt in run() die Funktion test() aufrufe klappt alles. Aber ich will ja auch mal die anderen Funktionen der Klasse aufrufen.

Beudeutet das, ich muss 3 verschiedene Klassen machen?
Das wäre ungeschickt, denn diese 3 Funktionen greiffen auf Variablen der Klasse in der momentan noch alle sind zu.
stefan-tiger
Beiträge: 49
Registriert: 28. März 2006 22:52

Beitrag von stefan-tiger »

Könnte mir jemand mal ein Beispiel machen, indem zwei QThreads aufgerufen werden?

Der eine gibt eine Variable auf der Konsole aus, der andere zählt diese Variable hoch.

Das würde mich wirklich wieterhelfen.

Vielen Dank.
Shadow
Beiträge: 92
Registriert: 27. August 2005 18:15
Wohnort: Iserlohn
Kontaktdaten:

Beitrag von Shadow »

stefan-tiger hat geschrieben:Könnte mir jemand mal ein Beispiel machen, indem zwei QThreads aufgerufen werden?

Der eine gibt eine Variable auf der Konsole aus, der andere zählt diese Variable hoch.

Das würde mich wirklich wieterhelfen.

Vielen Dank.
Das hängt ganz von dem zu lösenden Problem ab. Nutzt du shared-memory bei deinen read/write/test-Aktionen?
stefan-tiger
Beiträge: 49
Registriert: 28. März 2006 22:52

Beitrag von stefan-tiger »

Shadow hat geschrieben:...
Das hängt ganz von dem zu lösenden Problem ab. Nutzt du shared-memory bei deinen read/write/test-Aktionen?
Ich verstehe die Frage nicht ganz.

Kannst du mal bitte das Beispiel machen, denn das hat mit read/write/test nichts zu tun, das bezog sich auf ein USB-Gerät.
stefan-tiger
Beiträge: 49
Registriert: 28. März 2006 22:52

Beitrag von stefan-tiger »

Shadow hat geschrieben:...

Das hängt ganz von dem zu lösenden Problem ab...
Das eigentliche Problem ist folgendes:

Ich habe 3 Klassen: Meine Anwendung, die GUI und das USB-Gerät.

Die Anwendung hat die GUI und das USB.Gerät als Member.

Es soll, ohne, daß die GUI blockiert wird, vom USB-Gerät Daten empfangen werden und bei der GUI ggf. eine Funktion aufgerufen werden.

Das Selbe beim Schreiben auf das USB-Gerät.
An dem sind 8 LEDs dran. Zum Testen habe ich eine Sequenz (2 for Schleifen) Programmiert die die LEDs lecuhten lassen und das ganze dauert ca. 3-4 sekunden.
Das Problem ist dabei, wenn ich in der GUI auf einen Button klicke um die LEDs blinken zu lassen, dann ist die GUI für diese 3-4 Sek. wie eingefrohren.
Das möchte ich nicht.

Die Klasse von dem USB-Gerät enthält die Funktionen zum lesen (read) und schreiben (write) auf das USB-Gerät (test=LEDs blinken lassen). Ausserdem enthält die Klasse alle nötigen Informationen die man dazu braucht.

wenn ich jetzt aber

USB_Geraet::test();

per Button-Klick aufrufe, möchte ich gern, daß dies in einem seperaten Thread passiert, wegen obiger Problematik mit der GUI.

Folgendes hab ich dann probiert: ich habe

class USB_Geraet: public QThread

gemacht und in

USB_Geraet::run()

einfach

USB_Geraet::test()

aufgerufen. Das hat funktioniert.
Aber dabei ist ja run() mit test() fest verkettet. Ich sehe keine Möglichkeit die anderen Funktioen read() und write() der Klasse USB_Geraet ebenfalls in einem eigenen Thread von aussen aufzurufen.

Wurde ich jetzt aber eine extra Klasse für jede der drei Funktionen machen die von QThread abgeleitet ist, dann weiß ich nicht, wie ich auf die Member von der (Instanz der) Klasse "USB_Geraet" von den Threads aus zugreiffen kann.
Diese brauch ich aber denn diese Variablen enthalten Informationen für den Zugriff auf das am USB angeschlossene Gerät.

:)[/code]
Shadow
Beiträge: 92
Registriert: 27. August 2005 18:15
Wohnort: Iserlohn
Kontaktdaten:

Beitrag von Shadow »

stefan-tiger hat geschrieben:
Shadow hat geschrieben:...
Das hängt ganz von dem zu lösenden Problem ab. Nutzt du shared-memory bei deinen read/write/test-Aktionen?
Ich verstehe die Frage nicht ganz.

Kannst du mal bitte das Beispiel machen, denn das hat mit read/write/test nichts zu tun, das bezog sich auf ein USB-Gerät.
Schon ok, habe einen Deiner Posts übersehen:

- Du instanzierst eine Klasse, die die Funktionen test() u.s.w hat.
- Du erzeugst zwei Threads, die beide z.B. den Pointer auf diese Klasse mit den Funktionen verwenden (daher Shared Memory).
- In der run()-Routine des 1. Threads zählst du die Variable hoch.
- In der run()-Routine des 2. Threads gibst Du die Variable aus.

:!: Wenn allerdings zwei Threads auf einen gemeinsamen Speicher zugreifen, musst du die Threads bei Zugriffen auf gemeinsamen Speicher duch eine Semaphore (siehe QSemaphore) gegenseitig ausschließen, da diese Operationen "zaehlehoch()" und "ausgabe()" für sich atomar sind und es passieren kann, das genau zu diesem Zeitpunkt der andere Thread versucht, auf die gemeinsame Klasse zuzugreifen, um die ihm vorgegebene Operation "ausgabe()" bzw. "zaehlehoch()" durchzuführen. In diesem Fall würde es dann zu Zugriffsfehlern kommen.

Das bedeutet im Klartext:

Person A geht auf den Pott zum....
Person B geht jetzt auch geradewegs auf den Pott zu und will ihr Geschäft erledigen.
- Hat Person A vorher ordnungsgemäß abgeschlossen (Semaphore gesetzt), muss sie eben solange warten, bis Person A fertig ist und die Tür (Semaphore) öffnet. Person B kann jetzt loslegen.

- Hatte Person A aber nicht abgeschlossen, dann knallts kräftig! :D
Antworten