Seite 1 von 1

Qthread führt Methoden einfach nicht aus

Verfasst: 20. April 2009 21:38
von AlphaWolf
Ich bin hier schon fast am Verzweifeln. Ich möchte in meinem Workerthread ein paar Methoden ausführen jedoch weigert er sich hartnäckig irgendwas zu machen. Ich mache das ganze über eine Qt Message Loop:

Code: Alles auswählen

// Ogre initialisieren
// Ogre wird im schon im Workerthread initialisiert
m_pOgreManager = new OgreManager();
m_pOgreThread = new OgreThread(m_pOgreManager);
m_pOgreManager->moveToThread(m_pOgreThread);
m_pOgreThread->start();
QMetaObject::invokeMethod(m_pOgreManager, "initialize", Q_ARG(unsigned long, (unsigned long)renderWidget->winId()), Q_ARG(int, renderWidget->width()), Q_ARG(int, renderWidget->height()));
m_pOgreManager ist mein Objekt wo alle Sachen passieren sollen die innerhalb des Threads ablaufen sollen. Zunächst soll erstmal nur die Engine initialisiert werden. Dazu schiebe ich den OgreManager in meinen Thread, starte ihn und rufe dann die init Methode mit invokeMethod auf damit , sie in dem Thread von OgreManager gestartet wird.

So sieht meine run Methode im OgreThread aus:

Code: Alles auswählen

void OgreThread::run()
{
	// Wir wollen eine Nachrichtenschleife in unserem Thread
	exec();
}
Im Prinzip wird also nur die Nachrichtenschleife gestartet. Nachher wird noch der Rendervorgang gestartet aber erstmal muss der Thread überhaupt was tun.

Das Problem jetzt: Die Methode initialize wird niemals aufgerufen obwohl sie ja per QuedConnection dann von exec() aufgerufen werden sollte. Sehr komisch.

Verfasst: 20. April 2009 22:10
von franzf
Wie soll denn etwas passieren, wenn nix in run() drinnen steht?
Zeig doch wenigstens auch was in OgreManager::moveToThread() passiert.

Verfasst: 20. April 2009 22:28
von AlphaWolf
exec(); steht in run drin. Das sollte doch die Event-Loop ausführen, oder?

Code: Alles auswählen

Zeig doch wenigstens auch was in OgreManager::moveToThread() passiert.
OgreManager erbt von QObject. Ich dachte das wäre in diesem Zusammenhang klar.

Verfasst: 20. April 2009 23:15
von franzf
sry, war mir nicht klar.
Hab grad bissl probiert, aber ich hab keine Probleme das EventProcessing in den anderen Thread auszulagern.
Hast du schonmal den Rückgabewert von invokeMethod überprüft?
Und warum willst du das überhaupt über invokeMethod machen? Ruf die Funktion doch direkt auf, das EventHandling passiert sicher schon im anderen Thread!
hier mein test:

Code: Alles auswählen

//// obj.h ////

#ifndef OBJ_H
#define OBJ_H

#include <QObject>
#include <QThread>
#include <QDebug>
#include <QTest>

class Object : public QObject
{
    Q_OBJECT
    public:
        Object() : m_count(0) {
            connect(this, SIGNAL(done()), this, SLOT(doIt()));
        }
    public slots:
        void doIt() {
            qDebug() << "done!" << m_count++ << "in Thread:" << thread();
            QTest::qSleep(1000);
            emit done();
        }
    signals:
        void done();
    protected:
        int m_count;
};

class Thread : public QThread
{
    Q_OBJECT
    public:
        void run() {
            exec();
        }
};

#endif

//// main.cpp ////

#include <QPushButton>
#include <QApplication>
#include "obj.h"
#include <QDebug>

int main( int argc, char** argv )
{
    QApplication app( argc, argv );
    Object o;
    Thread t;
    qDebug() << "t-Thread:" << &t;
    qDebug() << "m-Thread:" << QApplication::instance()->thread();
    t.start();
    o.moveToThread(&t);
    QPushButton b("HelloQQQTTTT!");
    b.show();
    o.doIt();
    return app.exec();
}

Verfasst: 20. April 2009 23:50
von AlphaWolf
Wenn du die Methode direkt aufrufst wird sie im aufrufenden Thread ausgeführt. Ist ja eigentlich auch logisch. Daher wird eine DoIt Methode überhaupt nicht in deinem Thread ausgeführt.

Invoke schiebt die Methode in die EventLoop von dem Thread wo sie dann bei einem Durchlauf aufgegriffen und dann im thread ausgeführt wird.

Verfasst: 21. April 2009 07:24
von franzf
OK, aber auch damit gibts bei mir keine Probleme :/
Hab sogar nen unsigned long Parameter zu done/doIt hinzugefügt, um zu schauen ob es da zwickt. Aber auch so klappt alles.

Hast du denn den Rückgabewert von invokeMethod schon mal anzeigen lassen? Ist initialize auch WIRKLICH als Signal oder Slot definiert? Normale Methoden kannst du nicht per Signal/Slot weitergeben.

Falls das immer noch nix bringt, ist wohl mehr Code nötig, um zu sehen was falsch läuft.

Grüße
Franz

Verfasst: 21. April 2009 19:27
von AlphaWolf
Initialize war nicht als Slot definiert. Das war der entscheidende Hinweis. Danke franz!

Verfasst: 22. April 2009 12:42
von RHBaum
Dann noch als Hinweiss:

Wenn man mit dem Signal / Slot mechanismus arbeitet, sollt man die ausgabe auf der console oder im Debug fenster im Auge behalten. Wenn bei den connections irgendwas ned koscher ist, meldet es das Prog zu laufzeit(beim connect) da ...
Das hilft echt, laengere fehlersuche zu vermeiden !

Ciao ...

Verfasst: 29. April 2009 05:51
von forgoden
arbeitest du mit ogre grafik engine? und hauts gut hin?