Seite 1 von 1

[solved] QEventLoop und QThread

Verfasst: 20. Mai 2009 17:16
von cooky1976
Hallo,

ich muss leider nochmals ein altes Thema aufwärmen. Ich muss nun doch in einem QThread events abarbeiten. Allerdings kann ich nicht auf die QThread::exec() zurückgreifen, da ich die run() überschreiben musste.

Ich würde also gerne die EventQueue zwischendurch pollen.

Ich habe also in der klasse x definiert:

Code: Alles auswählen

connect(this, SIGNAL(test()), &thread, SLOT(test()),Qt::QueuedConnection);
und in der Thread-Klasse

Code: Alles auswählen

Testthread::run() {
    QEventLoop eventLoop;
...
    bool test = eventLoop.processEvents();
...
}
Aber selbst wenn ich das Signal emittiere, wird der Slot nicht aufgerufen. Wo ist denn da mein Problem?

Danke

Alexander

Verfasst: 20. Mai 2009 19:01
von franzf
Und warum machst du es nicht so wie in den Beispielen?

Code: Alles auswählen

void MyThread::run()
{
    Code();
    MoreCodeWithSignals();
    exec();
}

Verfasst: 20. Mai 2009 19:10
von cooky1976
Weil ich, wie ich schon geschrieben habe, eine eigene run()-Methode brauche und die ganze Zeit aktiv in dieser drin sein muss. Es wird da ein anderes Framework implementiert. Langer Rede kurzer Sinn, es geht einfach nicht.
Würde die exec() nur angestossen werden und die Verarbeitung würde weitergeben, wäre es kein Problem. Aber nachdem ja in der exec() verblieben wird, bis zum Threadende - no way.

Also nochmals zu meiner Frage .... gibt es eine Möglichkeit, die threadeigene Eventqueue anzupollen? Und wenn ja, wo ist mein Ansatzfehler?

Ich zitiere mal die Doku:
At any time, you can create a QEventLoop object and call exec() on it to start a local event loop
Aber irgendwie muss es ja auch ohne exec funktionieren.

Danke

Alexander

Verfasst: 20. Mai 2009 19:57
von franzf
Dann mach es doch so wie du es immer machst...
void QCoreApplication::processEvents ( QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents ) [static]

Processes all pending events for the calling thread according to the specified flags until there are no more events to process.
Dann noch ein bool loopStarted, welches Anfangs auf false ist, und nach dem exec() auf true gesetzt wird, damit exec() nur einmal aufgerufen wird. Und schon sind alle glücklich :)

Verfasst: 21. Mai 2009 14:04
von franzf
Ein exec() brauchst du scheinbar gar nicht. QCoreApplication::processEvents() reicht:

Code: Alles auswählen

#include <QThread>
#include <QDebug>
#include <QCoreApplication>

class Thread : public QThread
{
    Q_OBJECT
    public:
        Thread()
        {
            connect(this, SIGNAL(nextRun(int)), this, SLOT(on_nextRun(int)), Qt::QueuedConnection);
        }
    public Q_SLOTS:
        void on_nextRun(int val)
        {
            qDebug() << "run" << val;
        }
    Q_SIGNALS:
        void nextRun(int);
    protected:
        void run()
        {
            int start=111;
            while(true) {
                emit nextRun(start);
                start++;
                QCoreApplication::processEvents();
                QThread::msleep(1500);
            }
        }
};

Code: Alles auswählen

#include <QApplication>
#include <QSpinBox>
#include "thread.h"

int main( int argc, char **argv )
{
    QApplication app( argc, argv );
    Thread t;
    t.start();
    QSpinBox spin;
    spin.setRange(0, 99999);
    QObject::connect(&t, SIGNAL(nextRun(int)), &spin, SLOT(setValue(int)));
    QObject::connect(&spin, SIGNAL(valueChanged(int)), &t, SLOT(on_nextRun(int)));
    spin.show();
    return app.exec();
}
evtl. brauchst du noch im Konstruktor von Thread ein "this->moveToThread(this);"...

Grüße
Franz

Verfasst: 21. Mai 2009 14:18
von cooky1976
Franz, danke, ich hätte die Sache vielleicht auf solved stellen sollen, was ich jetzt machen werde. Und somit kann man relativ einfach eine run überschreiben ohne die exec zu benötigen.

Man muss nur die Doku genau lesen (und intuitiv in der QApplication nach multithread-spezifischen Funktionen suchen) ;-)