franzf hat geschrieben:....
Vllt. bin ich da [...] meintest du das mit den Cores?
Ich versuche mich mal an einem Beispiel:
Aufgabe1: eine Software muss 100 Bilder möglichst schnell verkleinern. Das Verkleinern (QPixmap::scaled()) selbst muss nicht abbrechbar sein, wohl aber der ganze Auftrag (z.B. Abbruch nach 30 Bildern). Möglichst schnell bedeutet, dass die Anzahl paralleler Aufträge mit den CPU-Cores übereinstimmt, denn wenn man 100 Bilder auf einem Quad-Core parallel konvertiert dauert das länger, als wenn immer 4 Aufträge in Arbeit sind

O-Zeit wird durch den "Ressourcen-Streit" verlängert und es gibt viel mehr Thread-Kontext-Wechsel).
Lösung: QtConcurrent, weil da Qt auf einem Quad-Core vier Threads wählt und auf einem Dual-Core zwei.. was jeweils die optimalste Lösung ist ohne dass ich mich als Entwickler um die Anzahl CPUs kümmern muss. Ein "scale" muss nicht abgebrochen werden, aber wenn der User auf "Abbruch" klickt, kann man über das Cancel-Management alle verbleibenden Aufträge verwerfen.
Aufgabe2: Eine Software soll von zwei USB-Kameras die Bilder so schnell wie möglich liefern. Der Bildfluss soll vom Anwender jederzeit ein/ausgeschaltet werden können.
Lösung: Zwei QThreads (abgeleitet oder mit zwei Kontroller-Klassen), weil die Anzahl Threads nicht von der CPU abhängt und man diese Aufgaben steuern muss (Signals/Slots, Flags/ Mutex.. irgendwie halt).
Stimmt das so?
RHBaum hat geschrieben:
Definier das mal genauer!
hmm.. ein paar Beispiele:
man hat einen QPushButton, einen QThread (nicht abgeleitet) und möchte auf Klick einen Slot in einer "Workerklasse" ausführen:
Vorbereitungen im Kontext des MainThreads (GUI):
Code: Alles auswählen
QPushButton *btn = findCh....
QThread *context = new QThread();
Worker *worker = new Worker();
Nun die connect/moveToThread-Varianten:
Code: Alles auswählen
connect(btn, SIGNAL(clicked()), worker, SLOT(doWork()));
Resultat: eine DirectConnection, welche doWork im GUI-Kontext ausführt, weil "btn" und "worker" zur gleichen Eventloop gehören.
Code: Alles auswählen
worker->moveToThread(context);
connect(btn, SIGNAL(clicked()), worker, SLOT(doWork()));
Resultat: eine QueuedConnection, welche doWork im Thread-Kontext ausführt weil "btn" und "worker" zu unterschiedlichen Threads gehören.
Code: Alles auswählen
connect(btn, SIGNAL(clicked()), worker, SLOT(doWork()));
worker->moveToThread(context);
Resultat: eine DirectConnection, welche doWork im GUI-Kontext ausführt, weil die Connection als "DirectConnection" gewählt wurde (die beiden QObjecte gehören zum Zeitpunkt von connect() zum gleichen Eventloop).
Code: Alles auswählen
connect(btn, SIGNAL(clicked()), worker, SLOT(doWork()), Qt::QueuedConnection);
worker->moveToThread(context);
Resultat: eine QueuedConnection, welche doWork im Thread-Kontext ausführt, weil die GUI-Eventloop das clicked()-Signal brav an den Thread weiterreicht.
Code: Alles auswählen
worker->moveToThread(context);
connect(btn, SIGNAL(clicked()), worker, SLOT(doWork()), Qt::DirectConnection);
Resultat: eine DirectConnection, welche doWork im GUI-Kontext ausführt, weil die GUI-Eventloop den Aufruf des Slots gleich selbst vornehmen muss..
ich hoffe das stimmt so 8)
[EDIT1]
RHBaum hat geschrieben:
Den fall hab ich eher seltener, meist krieg ich die aufgabe und hab threads sofort zur verfuegung, bzw erzug mir sofort welche (windows sei dank).
Das verstehe ich nicht so recht, denn QThread-sei-dank hat man das auf jeder Plattform jederzeit..
[EDIT2]
Habs ausprobiert: bei Variante 3 (moveToThread nach AutoConnection) lag ich falsch.. der Slot wird auch hier im Thread-Kontext ausgeführt... Eigentlich logisch, denn bei der AutoConnection wird ja erst beim konkreten Signal entschieden.. hübsch
