QMetaObject :: invokeMethod does not work when ...

... called from a static class and not the main thread. In short, I have a class "sapp" that has a static class "tobj" as a static member. To avoid static initialization fiasco, tobj is declared inside the sapp method, which in turn returns a pointer to the tobj instance. My problem is that tobj has a timer that must be run in the constructor, and tobj can be created not by the main thread. QTimer cannot be started by a thread, except for the main thread (or one that does not have an event loop, which I assume). for this reason I call QTimer :: start via QMetaObject :: invokeMethod + Qt :: QueuedConnection to avoid a thread problem, however it does not work, QTimer :: start is never called. I studied the problem a bit and looks like this: QTimer ::start is not called because the parent of QTimer (tobj in this case) is declared as static. If I declare tobj as a non-stationary member, everything works fine.

I don't understand Qt internals very well, maybe this is a mistake, or am I doing something wrong?

here is the code:

class tobj : public QObject
{
    Q_OBJECT

    QTimer timer;
private slots:
        void timeout();

public:
    tobj();
};

class sapp : public QObject
{
    Q_OBJECT

public:
    static tobj* f();
};


void tobj::timeout()
{
    qDebug() << "hi";
}

tobj::tobj()
{
    connect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
    timer.setInterval(500);
    qDebug() << QMetaObject::invokeMethod(&timer, "start", Qt::QueuedConnection); // returns true, but never invoked.
}

tobj* sapp::f()
{
    static tobj ff;
    return &ff;
}

Here is a link to a test project consisting of 1 header and 1 cpp file http://dl.dropbox.com/u/3055964/untitled.zip

I am testing Qt 4.8.0 and MSVC 2010.

Thank you so much, your help is greatly appreciated.

+3
source share
1 answer

I think you overdid it. The beauty of Qt is that what you are trying to do is very easy.

, , QTimer - , . Qt . Qt , , QObjects. , concurrency - Qt /. , , Qt , - , .

, , , - , timeout().

A QTimer , , , , QObject. QObjects , , QObject::moveToThread(QThread*).

invokeMethod . , , . , . , , a QMetaCallEvent QObject, . , . , , timeout().

, T main() QObject, , - , QtConcurrent. QtConcurrent QObject.

, , :

[] () {
    sapp s;
    s.f();
    QEventLoop l;
    l.exec();
}

SSCCE , Qt. QtConcurrent, : qApp->exit() exit() - a.exec() ( ?). wait() , main() - , QThreads, .

exit() , , , - API- C exit()s.

, a QTimer QObject . , , QBasicTimer, , QObject::startTimer(). QObject::timerEvent(). , . , ( ) , QStrings 1000 . . .

: , , - . 100 , . . , #include "filename.moc" filename.cpp. , Java. . , .

//main.cpp
#include <QtCore/QTimer>
#include <QtCore/QDebug>
#include <QtCore>
#include <QtCore/QCoreApplication>

class Class : public QObject
{
    Q_OBJECT
    QTimer timer;
    int n;
private slots:
    void timeout() {
        qDebug() << "hi";
        if (! --n) {
            QThread::currentThread()->exit();
        }
    }
public:
    Class() : n(5) {
        connect(&timer, SIGNAL(timeout()), SLOT(timeout()));
        timer.start(500);
    }
};

void fun()
{
    Class c;
    QEventLoop loop;
    loop.exec();
    qApp->exit();
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QtConcurrent::run(&fun);
    return a.exec();
}

#include "main.moc"
+4

All Articles