Frage

In meiner Anwendung gibt es den Haupt-Thread und ein Arbeitsthread (QThread).
Vom Haupt-Thread würde Ich mag eine Methode meiner Worker-Thread aufrufen und haben es in den Thread-Kontext ausführen.

Ich habe mit QMetaObject::invokeMethod versucht und ihm der QueuedConnection Option geben, aber es funktioniert nicht.
Ich habe auch versucht, Signale von dem Haupt-Thread emittierenden (die den Arbeiter-Thread des Schlitz verbunden ist), sondern daß auch fehlgeschlagen.

Hier ist ein Ausschnitt aus in etwa, was ich versuchte:

class Worker : public QThread
{
    Q_OBJECT

public:
    Worker() { }

    void run() 
    { 
        qDebug() << "new thread id " << QThread::currentThreadId(); 
        exec(); 
    }

public slots:
    void doWork()
    {
        qDebug() << "executing thread id - " << QThread::currentThreadId();
    }
};

Mit der QMetaObject Art und Weise:

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "main thread id - " << QThread::currentThreadId();

    Worker worker;
    worker.start();

    QMetaObject::invokeMethod(&worker, "doWork", Qt::QueuedConnection);

    return a.exec();
}

Mit dem Signal Art und Weise:

class Dummy : public QObject
{
    Q_OBJECT

public:
    Dummy() { }

public slots:
    void askWork() { emit work(); }

signals:
    void work();
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "main thread id - " << QThread::currentThreadId();

    Worker worker;
    worker.start();

    Dummy dummy;
    QObject::connect(&dummy, SIGNAL(work()), &worker, SLOT(doWork()), Qt::QueuedConnection);

    QTimer::singleShot(1000, &dummy, SLOT(askWork()));

    return a.exec();
}

Beide Wege führen zu den Haupt-Thread-ID in der QThread doWork gedruckt wird.

Auch dachte ich an einem einfachen Erzeuger-Verbraucher-Umsetzung, aber wenn das funktioniert, gibt es keinen Grund, warum es nicht auf diese Weise zu tun?

War es hilfreich?

Lösung

Das Problem war, dass der Empfänger (die QThread) Leben "in dem Haupt-Thread und damit die Ereignisschleife des Haupt-Threads ist die, dass der Schlitz ausgeführt wird.

von Qt-Dokumentation:

  

Mit Verbindungen der Warteschlange ist der Schlitz aufgerufen, wenn die Steuerung kehrt zu der Ereignisschleife des Fadens zu dem das Objekt gehört. Der Schlitz ist in dem Thread ausgeführt, wo der Empfänger Objekt lebt.

So ist die Lösung, die ich bisher gefunden wurde, ein Objekt innerhalb des Threads laufen zu erstellen () und das Schlitze stattdessen verwenden. Auf diese Weise Besitzer des Empfängers ist der rote Faden, und dann wird der Schlitz im Gewinde Kontext genannt.

Andere Tipps

Dieses Beispiel zeigt, wie Sie die Arbeiterklasse spalten kann, damit es funktioniert, wie Sie wollen. Sie müssen auch einen Verweis oder Zeiger auf die Worker-Instanz in der Lage sein, um mit dem Schlitz zu verbinden.

class Worker : public QObject
{
    Q_OBJECT

public:
    Worker() { }

public slots:
    void doWork()
    {
        qDebug() << "executing thread id - " << QThread::currentThreadId();
    }
};

class WorkerThread : public QThread
{
    Q_OBJECT

public:
    void run()
    {
        qDebug() << "new thread id " << QThread::currentThreadId(); 
        Worker worker;
        exec();
    }
};

Für den einfachen Erzeuger-Verbraucher haben beispielsweise einen Blick auf den Blog-Eintrag von Bradley T. Hughes Treading ohne die Kopfschmerzen .

Der Arbeiter ist in dem Haupt-Thread erstellt, und daher ist es Ereignisse im Hauptthread proccessed werden. Sie müssen die Arbeiter, um es einem eigenen Thread verschieben:

Worker worker;
worker.moveToThread(&worker);
worker.start();

Jetzt Qt weiß worker Leben in dem neuen Thread, und Ereignisse in dieser Ereignisschleife Warteschlange.

Es sieht aus wie Ihr Arbeitsthread vor vervollständigt können Sie auch eine beliebige Funktion aufrufen oder ein Signal an sie senden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top