2016-05-24 18 views
1

Ich habe eine Anwendung, die kontinuierlich ein Bild von einer Kamera liest und dies einem Benutzer anzeigt. Der Benutzer kann verschiedene Schieberegler wie Belichtung und Schwellenwert anpassen, um das Bild in Echtzeit zu ändern. Ich mache auch eine Reihe von Berechnungen für dieses Bild, was manchmal dazu führt, dass die GUI nicht mehr reagiert. Daher entschied ich mich, Threads zu verwenden, um die Arbeitslast zu teilen.So verwenden Sie Threads in Qt GUI

Allerdings kann ich es nicht richtig funktionieren, manchmal bekomme ich Segmentierung Fehler und eine Reihe von "Assertion` GLib-GObject-CRITICAL **: g_object_unref: Behauptung 'G_IS_OBJECT (Objekt)' fehlgeschlagen "Warnungen, wenn die Schiebereglerwerte werden geändert oder wenn ich versuche, das Bild zu speichern (Schaltfläche "Speichern" in meiner GUI), und die GUI hält manchmal an, das Bild zu aktualisieren oder friert ein, so dass Sie die Schieberegler nicht verschieben oder Tasten drücken können.

Was ich versuchte, war die Verwendung der Standard-Std :: Thread in C++, und verbinden Sie es über einen Steckplatz mit der Start-Taste.

QObject::connect(btnStart, SIGNAL(clicked()), this, SLOT(RunStartThread())); 

void MainMenu::RunStartThread(){ 
std::thread t1; 
t1= std::thread(&MainMenu::Start,this); 
t1.detach(); 
} 

void MainMenu::Start() { 
run = true;  
    window->mngr->ReadCalibration(); 
    window->mngr->InitializeCameras(); 

    while (run) { 

     window->mngr->CaptureImage(); 
     window->mngr->ProcessImages();    
     UpdateLabels(); 
     } 

window->mngr->Stop(); 
} 

Wenn der Benutzer die Schieberegler Werte, die sie Variablen in meinem Manager (mngr oben) ändern ändert, dass captureImage und ProcessImages verwendet. Ich versuchte mit einem std :: mutex lock/entsperren, wenn auf eine Variable zugegriffen werden sollte, aber es änderte nichts. Ich habe versucht, Beispiele dafür zu finden, wie man das online macht, aber ich muss noch etwas finden, das eine kontinuierliche While-Schleife hat.

Ich bin ein Neuling, wenn es um Threads geht, also sag mir einfach, wenn ich mich dem falsch annähere.

+2

Vielleicht sollten Sie besser [QThread] (http://doc.qt.io/qt-5/qthread.html) verwenden? – someoneinthebox

+0

Hoffentlich greifen die Funktionen Ihrer mngr-Instanz nicht direkt auf QT-Widgets zu. Wenn Sie innerhalb des zweiten Threads (UpdateLabels()?) Änderungen in der GUI vornehmen wollen, müssen Sie dies auch über Signal/Slot tun! – Aconcagua

+0

Die Updates von den Slidern werden über Signal/Slot verwaltet, und der Manager hat überhaupt keinen Zugriff auf die Qt-Widgets. Die GUI hat eine Verbindung zum Manager, aber nicht umgekehrt. UpdateLabels erhält einfach einige Bildinformationen vom Manager und aktualisiert Etiketten in der GUI. Tut mir leid, dass ich nicht geklärt habe. Ich habe versucht, in Qthread zu suchen, aber ich habe keine guten Beispiele dafür gefunden, wie es geht. – user3518432

Antwort

1

Zuerst für alle für Inter-Thread-Kommunikation verwenden Singeln und Slots. Standardmäßig führen Qt-Verbindungen ein nettes Thread-Hopping zwischen Threads durch, wodurch eine komplexe Synchronisation vermieden werden kann.

Zweitens haben Sie drei Möglichkeiten, Threads zu verwenden: QThread, QRunnable, QtConcurrent::Run (mein Favorit, da erfordert Mindestmenge an Code).

Im Fall QThread bitte nicht Unterklasse! Es ist common design mistake.

Beispiel:

SomeClass::~SomeClass() 
{ 
    SignalStop(); 
    future.result(); 
} 

void SomeClass::RunStartThread(){ 
    future = QtConcurrent::run(this, &SomeClass::DoOnThread); 
} 

void SomeClass::DoOnThread() 
{ 
    while (ShouldContinueToRun()) { 
     QImage im1 = CaptureImage(); 
     emit ImageCaptured(im1); 
     QImage im2 = ProcessImages(im1);    
     emit ImageProcessed(im2); 
    } 
    emit JobCompleted(); 
} 

Bitte beachten Sie, dass QObject::connect letztes Argument hat, die definiert, wie Aufruf von Schlitz durchgeführt wird, wenn unterschiedliche Gewinde beteiligt ist. Siehe documentation of enumeration für dieses Argument verwendet.
Standardmäßig erkennt Qt, ob Thread-Hopping erforderlich ist oder nicht. Das sorgfältige Lesen von QObject::moveToThread sollte ebenfalls helfen, das Problem zu verstehen (beachten Sie, dass Sie das Objekt nicht in einen anderen Thread verschieben können, wenn es einen Elternteil hat).

+0

Nach Ihrem Link, dann in Ihrem Beispiel, hätte 'SomeClass' nicht von' QThreadPool' zu erben? Ich würde eher erwarten, dass "doOnThread" statisch ist und einen Parameter 'SomeClass *' hat und 'run (& doOnThread, this);'. Was habe ich verpasst? – Aconcagua

+0

Wenn die Bilder mit opencv's imshow angezeigt werden, muss ich wirklich ein Signal aussenden, dass das Bild aufgenommen wurde? Verarbeitet sicher, da update labels davon abhängt. Aber wie würde ich dieses Signal mit der updateLabels() Funktion/Slot verbinden? Wie mit dem JobCompleted, wie verbinde ich dieses Signal mit meinen Funktionen? – user3518432

+0

@Aconcagua Siehe [dieser Teil der Dokumentation] (http://doc.qt.io/qt-5/qtconcurrentrun.html#using-member-functions). – thuga