2010-07-09 12 views
8

ich eine einfache Form UI haben, die einen Steckplatz für eine Taste hat, beginnen einen Thread:QThread Blockierung Haupt

void MainWindow::LoadImage() 
{ 
    aThread->run(); 
} 

Und die Methode run() sieht wie folgt aus:

void CameraThread::run() 
{ 
    qDebug("Staring Thread"); 
    while(1) 
    { 
     qDebug("ping"); 
     QThread::sleep(1); 
    } 
} 

Wenn Ich klicke auf die Schaltfläche, die LoadImage() aufruft, die Benutzeroberfläche reagiert nicht mehr. Ich sehe regelmäßig die "Ping" Nachricht als Debug-Ausgabe, aber die UI hängt, reagiert auf nichts. Warum wird mein Thread nicht separat ausgeführt? CameraThread abgeleitet als öffentliche QThread Ich benutze gcc Version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) mit QT-Bibliotheken und QT Creator von Ubuntu 10.04 (x86) Repositories.

Antwort

27

Kurze Antwort: Thread starten von aThread->start(); nicht run() Aufruf, und stellen Sie sicher, dass Sie die (Laufgewinde) Methode ist geschützt (nicht öffentlich).

Erläuterung

Calling start() is the correct way den Faden zu starten, wie es Prioritätsplanung liefert, und führt tatsächlich die run() Verfahren in einem eigenen Thread-Kontext.

Es ist wie Sie Bilder in diesem Thread werden werden Laden aussieht, so werde ich einige Tipps enthalten, bevor Sie in Fallen laufen viele Menschen fallen in während der Verwendung QThread

  1. QThread selbst nicht ist ein Thread. Es ist nur ein Wrapper um ein Gewinde, das uns bringt ..
  2. Signale/in der CameraThread Klasse definiert Schlitze nicht notwendigerweise im Kontext des Thread ausgeführt, erinnere mich nur an die Methode run() und Methoden aus sie aufgerufen laufen in einem separaten Thread.

IMHO, Subklassen QThread in der Mehrheit der Fälle ist nicht der Weg zu gehen. Sie können es viel einfacher mit dem folgenden Code tun, und es wird Ihnen helfen, viele Kopfschmerzen.

class ImageLoader : public QObject { 
Q_OBJECT 
public slots: 
    void doWork() 
    { 
     // do work 
    } 
}; 

void MainWindow::MainWindow(/*params*/) 
{ 
    ImageLoader loader; 
    QThread thread; 
    loader.moveToThread(&thread); 
    connect(this, SIGNAL(loadImage()), &loader ,SLOT(doWork())); 
    thread.start(); 
    // other initialization 
} 
void MainWindow::LoadImage() 
{ 
    emit loadImage(); 
} 

Lesen Sie auch die Qt blog zu diesem Thema.

+0

Die QT-Dokumentation erläutert die Verwendung von QThread durch Unterklassen. Warum ist das eine schlechte Idee? –

+1

@Atilla - wenn Sie QT Blog Link in Caseys Antwort lesen, finden Sie es mit dem Titel "Sie tun es falsch ...". Es ist eine Diskussion darüber, warum die Dokumentation von Qt über das Unterklassen von QThread nicht die richtige Vorgehensweise für Threads ist.Wenn ich den Blogeintrag richtig gelesen habe, ist es auch die Person, die die ursprüngliche Qt-Dokumentation geschrieben hat. –

+2

Ja, das stimmt. Grundsätzlich ist die Qt-Dokumentation irreführend und hat viele Leute dazu gebracht, Hacky-Dinge zu machen (wie movetoThread (this) im Qthread-Konstruktor), die Probleme auf der ganzen Linie verursachen. Hoffentlich wird die Dokumentation in Kürze aktualisiert werden. – Casey

4

Sie müssen thread-> start() nicht ausführen ... run ist ein Einstiegspunkt für Thread. Der Thread wird mit Start gestartet. Du rufst direkt an, deshalb blockierst du deine GUI. Überprüfen Sie die Dokumentation von QThread. virtual void QThread :: run() ist geschützt (nicht ohne Grund)

-1

Ich denke, das Problem könnte sein, dass Sie QtCore.QThread._init __ (self) im Konstruktor nicht aufrufen. Ich hatte das gleiche Problem. Ich denke auch, dass Sie die Startfunktion nicht überschreiben sollten, überschreiben Sie einfach die Funktion run(). Dies löste das gleiche Problem, das ich hatte. Auch ohne Verzögerungen() sollte das Fenster reagieren.

+1

Nein, mein Problem war run() stattdessen aufrufen von Anfang(). Ich habe schon übersteuert(). –