我有一個以下列方式實現的活動對象。它用於在後臺執行長時間的任務。主線程通過向公共時隙發送信號來調用任務(即,doTask)。這是一個精簡的例子(未經測試)。沒有連接的調用槽方法?
class MyTask : public QObject
{
Q_OBJECT
public:
MyTask();
~MyTask();
public slots:
void doTask(int param);
private slots:
void stated();
signals:
void taskCompleted(int result);
private:
QThread m_thread;
};
MyTask::MyTask()
{
moveToThread(&m_thread);
connect(&m_thread, SIGNAL(started()), this, SLOT(started()));
m_thread.start();
}
MyTask::~MyTask()
{
// Gracefull thread termination (queued in exec loop)
if(m_thread.isRunning())
{
m_thread.quit();
m_thread.wait();
}
}
void MyTask::started()
{
// initialize live object
}
void MyTask::doTask(int param)
{
sleep(10);
emit taskCompleted(param*2);
}
只要信號調用doTask(),該(應該)按預期工作。但是,如果主線程直接調用doTask(),它將由主線程執行。對於某些任務,即使插槽方法是直接調用的,我也希望通過活動對象的線程強制執行。
我可以在doTask()前添加代碼來檢查當前線程是否是m_thread,在這種情況下它會執行該方法。如果不是,我希望doTask()向'this'發出一個信號,以便調用doTask()在m_thread exec循環中排隊並儘快執行。
我該怎麼做?
編輯:基於建議的答案,這裏是新的代碼。即使直接由主線程調用,doTask方法現在也會委託活動objet的線程執行。通過信號調用仍然按預期工作。
class MyTask : public QObject
{
Q_OBJECT
public:
explicit MyTask(QObject *parent = 0);
~MyTask();
public slots:
void doTask(int param);
private slots:
void doTaskImpl(int param);
signals:
void taskCompleted(int result);
private:
QThread m_thread;
};
MyTask::MyTask(QObject *parent) : QObject(parent)
{
moveToThread(&m_thread);
m_thread.start();
}
MyTask::~MyTask()
{
// Gracefull thread termination (queued in exec loop)
if(m_thread.isRunning())
{
m_thread.quit();
m_thread.wait();
}
}
void MyTask::doTask(int param)
{
QMetaObject::invokeMethod(this, "doTaskImpl", Q_ARG(int, param));
}
void MyTask::doTaskImpl(int param)
{
// Do the live oject's asynchronous task
sleep(10);
emit taskCompleted(param*2);
}
這是我能找到的最簡單的實現來支持在單獨的線程中執行異步方法。只要線程啓動,doTask()方法的調用就會排隊並處理。當從對象線程調用時,它將立即執行(不排隊)。
請注意,只有在啓動線程時纔會發出啓動()信號。這意味着在啓動線程之前排隊的doTask()方法調用將在啓動()方法插槽被調用之前執行。這是我從初始實施中刪除它的原因。因此,對象初始化應該最好在構造函數中執行。
我看到這裏有一個問題正確,則
moveToThread(&m_thread);
將失敗有一位家長。如果MyTask是由父級創建的,您的代碼是否工作? – andref 2010-07-28 14:18:19
一個類似的問題也已經在[QT +如何從不同線程中運行的自定義C++代碼中調用插槽](http:// stackoverflow。COM /問題/ 1144240/QT-如何撥號槽 - 從定製-C代碼運行-IN-A-不同的線程)。 – Trilarion 2014-05-23 09:35:05