2009-08-01 13 views
5

在我的應用程序中有主線程和工作線程(QThread)。
從主線程我想調用我的工作線程的方法,並讓它在線程的上下文中運行。在QThread的上下文中調用方法

我試過使用QMetaObject::invokeMethod並給它QueuedConnection選項,但它不起作用。
我也嘗試從主線程(它連接到工作線程的插槽)發出信號,但也失敗了。

這裏有大約一個片段是我的嘗試:

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(); 
    } 
}; 

使用QMetaObject方式:

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(); 
} 

使用的信號方式:

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(); 
} 

兩種方式都導致主線程ID正在打印在QThreaddoWork中。

此外,我想實現一個簡單的生產者 - 消費者,但如果這個工程,是否有任何理由不這樣做?

回答

3

問題在於接收者(QThread)在主線程中'生存',因此主線程的事件循環是執行該插槽的事件循環。

從Qt的文檔:

隨着排隊連接,則控制返回到線程的事件循環對象所屬當槽被調用。該插槽在接收器對象所在的線程中執行。

所以我到目前爲止發現的解決方案是在線程的run()中創建一個對象,並使用它的槽來代替。這樣接收方的所有者就是線程,然後在線程環境中調用該插槽。

0

它甚至可以調用任何函數或向其發送信號之前看起來像您的工作線程完成。

+1

由於調用exec()函數,工作線程在事件循環中, – 2009-08-01 18:49:57

2

這個例子顯示瞭如何分解Worker類,使其工作。您還需要提供參考或指向Worker實例的指針才能連接到插槽。

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(); 
    } 
}; 
1

職工在主線程創建的,因此它的事件在主線程處理連線。你必須移動到工人它自己的線程:

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

現在的Qt知道worker生活在新線程,並且將排隊在事件循環事件。

相關問題