首先必須明確的是,Qt中的線程使用是相對復雜的,並不像C#中那麼隨意,特別是結合串口、網絡編程等,使用時稍有不慎就會出問題,然後Qt裡面經常出了問題就直接崩潰(這個真是誰用誰知道),所以如果在功能上用異步方式能做到其實就沒必要自己去開線程,當然如果自己寫的函數比較耗時(比如不斷地循環做操作之類的)就無法避免使用線程了。
Qt中一般將耗時操作單獨放在一個類中實現,在主線程中創建類對象,然後將這個對象移到子線程中,主線程與子線程間的通信主要通過信號和槽實現。另外對象是在主線程中創建的,對象中的成員都屬於主線程,在主、子線程中都可以直接訪問,不過如果你把對象中的成員也移到子線程中,那麼在主線程就不能直接訪問這個成員了。
下面是一個使用實例。
class ThreadManager : public QObject
{
Q_OBJECT
QThread workerThread;
public:
ThreadManager();
~ThreadManager();
MyWorker * worker;
signals:
void start();
public slots:
void emitstart();
void emitstop();
void printThreadId(int count);
};
ThreadManager::ThreadManager()
{
worker = new MyWorker();
worker->moveToThread(&workerThread);
connect(this,SIGNAL(start()),worker,SLOT(Start()));
connect(worker,SIGNAL(invokeParentThreadMethod(int)),this,SLOT(printThreadId(int)));
workerThread.start();
}
ThreadManager::~ThreadManager()
{
workerThread.quit();
}
void ThreadManager::emitstart()
{
emit start();
}
void ThreadManager::emitstop()
{
worker->stoped = true;
qDebug()<<"停止";
}
void ThreadManager::printThreadId(int count)
{
//worker->stoped = true;
qDebug()<<QThread::currentThreadId()<<"\t"<<count;
}
ThreadManager 用來開啟一個新的線程,然後在這個線程裡面執行其他操作,下面是執行操作的類 MyWorker。
class MyWorker : public QObject
{
Q_OBJECT
public:
explicit MyWorker(QObject *parent = 0);
bool stoped;
signals:
void invokeParentThreadMethod(int count);
public slots:
void Start();
};
MyWorker::MyWorker(QObject *parent) :
QObject(parent)
{
stoped = false;
}
void MyWorker::Start()
{
int count =0;
stoped = false;
while(!stoped)
{
qDebug()<<QThread::currentThreadId()<<"\t"<<count++;
emit invokeParentThreadMethod(count);
QThread::msleep(500);
}
}
再看看我們在主線程中如何使用的
QObject* win = engine.rootObjects()[0];
QObject* Button_Start = win->findChild<QObject*>("Button_Start");
QObject* Button_Stop = win->findChild<QObject*>("Button_Stop");
ThreadManager* therad = new ThreadManager();
QObject::connect(Button_Start,SIGNAL(clicked()),therad,SLOT(emitstart()));
QObject::connect(Button_Stop,SIGNAL(clicked()),therad,SLOT(emitstop()));
這裡只是一個很簡單的線程使用示例,在串口、網絡編程時往往涉及到線程同步、資源共享、線程通信等問題,比如子線程還在使用資源主線程卻將資源釋放了或是線程間通信時傳過去的數據發生了變化等等,具體情況只有結合自己經驗去分析了。