Warum ist QThread::finished signal nicht emittiert werden?
Habe ich mein eigenes erstellt TestService
läuft auf einem separaten QThread
, aber wenn die MainLoop
beendet die QThread::finished
signal nicht ausgegeben. Ich sah eine ähnliche Frage, aber das problem war etwas anders da, weil der OP war eine überlastung QThread
während ich bewege einfach meine Klasse zu dem thread.
Beachten Sie, dass ich nicht überlasten die QThread
Klasse, ich kann nur überlastung QObject
basierend auf diesem Beispiel: http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
Hier ist mein TestService
Klasse:
#include <QObject>
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <iostream>
using namespace std;
class TestService: public QObject
{
Q_OBJECT;
private:
volatile int _count;
QWaitCondition _monitor;
QMutex _mutex;
QThread* _thread;
public:
TestService(int numSeconds)
{
_count = numSeconds;
_thread = NULL;
cout << "TestService()" << endl;
}
virtual ~TestService()
{
cout << "~TestService()" << endl;
}
void Start()
{
QMutexLocker locker(&_mutex);
if(_thread == NULL)
{
_thread = new QThread;
//Move this service to a new thread
this->moveToThread(_thread);
//The main loop will be executed when the thread
//signals that it has started.
connect(_thread, SIGNAL(started()), this, SLOT(MainLoop()));
//Make sure that we notify ourselves when the thread
//is finished in order to correctly clean-up the thread.
connect(_thread, SIGNAL(finished()), this, SLOT(OnFinished()));
//The thread will quit when the sercives
//signals that it's finished.
connect(this, SIGNAL(Finished()), _thread, SLOT(quit()));
//The thread will be scheduled for deletion when the
//service signals that it's finished
connect(this, SIGNAL(Finished()), _thread, SLOT(deleteLater()));
//Start the thread
_thread->start();
}
}
void Stop()
{
_count = 0;
_monitor.wakeAll();
}
private slots:
void MainLoop()
{
cout << "MainLoop() Entered" << endl;
while(_count > 0)
{
cout << "T minus " << _count << " seconds." << endl;
QMutexLocker locker(&_mutex);
_monitor.wait(&_mutex, 1000);
_count--;
}
cout << "MainLoop() Finished" << endl;
emit Finished();
}
virtual void OnFinished()
{
cout << "OnFinished()" << endl;
}
signals:
void Finished();
};
Hier ist der Test-code:
void ServiceTest()
{
cout << "Press q to quit." << endl;
cout << "Press s to start." << endl;
cout << "Press t to stop." << endl;
QSharedPointer<TestService> testService(new TestService(10));
char in = 'a';
while( in != 'q' )
{
switch(tolower(in))
{
case 's':
testService->Start();
break;
case 't':
testService->Stop();
break;
default:
break;
}
cin.get(in);
in = tolower(in);
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
ServiceTest();
QTimer::singleShot(0, &a, SLOT(quit()));
return a.exec();
}
Ausgabe:
Press q to quit.
Press s to start.
Press t to stop.
TestService()
s
MainLoop() Entered
T minus 10 seconds.
T minus 9 seconds.
T minus 8 seconds.
t
MainLoop() Finished
q
~TestService()
Press any key to continue . . .
Kann jemand erklären, warum ist finished
nicht ausgestoßen, wie ich es beheben kann?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Signal finished() wird emittiert von der Ursache, aber Sie nicht fangen.
Hier:
Qt::QueuedConnection
verwendet wird, als_thread
undthis
(Dienst), die in verschiedenen threads.Durch die Zeit
finished()
emittiert wird,_thread
's event loop schon fertig ausgeführt, so wird kein signal geliefert, um den Steckplatz.Können Sie explizit
Qt::DirectConnection
.EDIT:
QTherad funktioniert wie folgt:
So, durch die Zeit, die
finished
emittiert wird, eventloop bereits beenden Sie die Ausführung. Und wie bewegen Sie sichservice
zu_thread
-, service-event-Schleife ist_thread
event-Schleife.Beachten Sie, dass
QObject
selbst hat keine eigene event-Schleife. Event-loops erstellt von Dialogen, threads und Anwendung.Eigentlich werde ich empfehlen, in deinem einfachen Fall verwenden Sie einfach
QtConcurent::run
, wie Sie führen keine eigentliche event processing in den neuen thread, aber führen Sie einfach eine einzige Funktion.TestService
nicht überlastetQThread
- es nur überlastungenQObject
. Das Beispiel, das ich basiert mein code ist hier: mayaposch.wordpress.com/2011/11/01/... in Bezug auf dieQtConcurrent::run
würde ich lieber nicht verwenden, um boost für dieses Beispiel, da bin ich strikt versuchen zu kleben, um Qt-Bibliotheken nur.QtConcurent::run
ist voll von Qt und der Feststellung zu tun, mit boost.QtCurrent::run
verwendetboost::bind
. vielen Dank für die aktualisierte Antwort: was ich bin immer noch verwirrt darüber ist, was Sie meinen, wenn Sie sagen, dass, wennfinished()
emittiert wird, die_thread
's-event-Schleife ist bereits fertig ausgeführt wurde... ich bin nicht versucht, Sie zu verarbeiten in der_thread
's-event-Schleife, aber in derTestService
's event loop. Wenn ich das richtig verstanden, dieTestService
Ereignis-Schleife sollte immer noch aktiv sein, da der Dienst wurde nicht zerstört.QtConcurrent::run
ohneboost::bind
ich werde versuchen einen Weg zu finden, dieses Problem zu beheben.QtConcurrent::run
war eine tolle Lösung! Danke!QThread::started()
signal verarbeitet, obwohl er keine Ereignis-Schleife gehen? Es sollteQt::QueuedConnection
genau wie dieQThread::finished()
Verbindung. Durch die gleiche Argumentation, QThread::Start() darf nie verarbeitet haben.QThread::finished()
signal ist das Objekt, das in einem thread mit nicht-event-Schleife, so dass sein problem war, dass der Schlitz war noch nie ausgelöst, nicht, dass das signal nie emittiert.