Ich habe Probleme mit Qt Threads und Verbindungen. Ich fand mehrere Tutorials und Diskussionen zu diesem Thema, ich folgte this tutorial, um den Thread zu erstellen. Aber ich habe immer noch das Problem, dass das Aufrufen von wait() auf dem Thread nie zurückkehrt und die Benutzeroberfläche einfriert.QThread :: wait() kehrt nicht ohne direkte Verbindung zurück
Eine ähnliche Frage gestellt wurde hier vor (das zweite Beispiel): Qt connection type between threads: why does this work?
In der letzten Bearbeitung der Frage, erwähnt der Autor, dass er eine Sackgasse geschaffen hatte. Ich nehme an, ich mache das gleiche in meiner Bewerbung. Aber ich verstehe immer noch nicht, warum das passiert. Das Lesen der suggested article half mir nicht zu verstehen. Ich habe gerade verstanden, dass Deadlocks passieren können, aber ich weiß nicht, was es dort oder in meinem Fall verursacht.
ich geschaffen habe auch ein Beispiel, das auf das Kernproblem reduziert wird. Suchen Sie den Code am Ende dieser Frage.
Also meine Fragen sind: Was genau die Ursache für den Stillstand in meinem Beispiel ist? Gibt es eine Lösung, ohne die Verbindung direkt zu verbinden?
Ich würde wirklich irgendwelche Hinweise zu schätzen wissen.
Danke!
EDIT:
Aufgrund der Kommentare I versucht, die Stoppanforderung über ein Signal zu senden und I hinzugefügt, um einen QCoreApplication :: process() -Aufruf in der Fadenschlaufe. Aber das Hauptproblem ist immer noch das gleiche.
EDIT2:
ich eine akzeptable Lösung gefunden, nach ein wenig mehr über Event denken Schleifen:
thread.requestStop();
// now instead of using wait(), we poll and keep the event loop alive
// polling is not nice, but if it does not take a very long time
// for the thread to finish, it is acceptable for me.
while (thread.isRunning())
{
// This ensures that the finished() signal
// will be processed by the thread object
QCoreApplication::processEvents();
}
Das funktioniert tatsächlich und der Arbeiter selbst steuert, wie funktioniert.
Nachdem mit diesem kommen, ich habe auch eine Erklärung für das Einfrieren Problem: Warten Aufruf des Haupt-Thread entweder besetzt oder suspendiert zu halten scheint, so dass es keine Ereignisse verarbeiten hat. Da das Thread-Objekt im Haupt-Thread lebt, wird das finished() -Signal des Threads abgefragt, aber nie verarbeitet.
Meine implizite Annahme, dass thread.wait() noch die Ereignisschleife weiter arbeiten würde, war offensichtlich falsch. Aber für was ist die QThread :: wait() - Funktion gut?!? Diese
ist nur eine Theorie, aber vielleicht jemand hier kann es verifizieren oder falsifizieren ...
EDIT 3 (Endlösung):
Nach this small article Lesen und eine Subklassifizieren Lösung implmenting, ich glaube, dass dies für dieses spezielle Problem vorzuziehen ist. Es gibt keine Notwendigkeit für eine Ereignisschleife und mir geht es gut mit direkten Aufrufen auf einem anderen Thread und Mutex-Schutz verwenden. Es ist weniger Code, einfacher zu verstehen und einfacher zu debuggen.
Ich denke, ich würde die Nicht-Unterklassen-Strategie nur verwenden, wenn es mehr Interaktion mit dem Thread als nur starten und pausieren würde.
Mein reduziert Beispiel
Vielleicht sollte ich darauf hinweisen, dass ich nicht löschen den Faden, weil in meiner ursprünglichen Anwendung, wie ich später wieder aufnehmen wollen, so dass es tatsächlich zu stoppen, bedeutet es eine Pause.
worker.h:
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
#include <QMutex>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject* parent = NULL);
public slots:
void doWork();
void requestStop();
signals:
void finished();
private:
bool stopRequested;
QMutex mutex;
};
#endif // WORKER_H
worker.cpp:
#include "worker.h"
#include <QThread>
#include <iostream>
using namespace std;
Worker::Worker(QObject *parent)
: stopRequested(false)
{
}
void Worker::doWork()
{
static int cnt = 0;
// local loop control variable
// to make the usage of the mutex easier.
bool stopRequesteLocal = false;
while (!stopRequesteLocal)
{
cout << ++cnt << endl;
QThread::msleep(100);
mutex.lock();
stopRequesteLocal = stopRequested;
mutex.unlock();
}
cout << "Finishing soon..." << endl;
QThread::sleep(2);
emit finished();
}
void Worker::requestStop()
{
mutex.lock();
stopRequested = true;
mutex.unlock();
}
Hauptprogramm:
#include <QCoreApplication>
#include <QThread>
#include <QtCore>
#include <iostream>
#include "worker.h"
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QThread thread;
Worker worker;
QObject::connect(&thread, SIGNAL(started()), &worker, SLOT(doWork()));
// this does not work:
QObject::connect(&worker, SIGNAL(finished()), &thread, SLOT(quit()));
// this would work:
//QObject::connect(&worker, SIGNAL(finished()), &thread, SLOT(quit()), Qt::DirectConnection);
// relocating the moveToThread call does not change anything.
worker.moveToThread(&thread);
thread.start();
QThread::sleep(2);
worker.requestStop();
cout << "Stop requested, wait for thread." << endl;
thread.wait();
cout << "Thread finished" << endl;
// I do not know if this is correct, but it does not really matter, because
// the program never gets here.
QCoreApplication::exit(0);
}
'Schlaf' a in Qt geschützt ist, wie kann man QThread :: Schlaf (2) nennen; ?? – UmNyobe
Ich weiß es nicht. Ich mache es einfach und es funktioniert. ;) – Kanalpiroge
Das ist nicht möglich :) Hast du die Qt-Quelle bearbeitet? –