默默地EEer,原文地址:
http://www.cnblogs.com/hebaichuanyeah/p/5618781.html
在調用linux環境下線程API寫Cpp時,發現異常蛋疼,要么線程函數不能是類的成員函數,要么必須是類的static成員函數(意味着調用的成員變量也必須是static……其實還是不屬於類)。
Qt提供一套線程機制,只要繼承QThread基類並重新實現void run()函數即可。
新建thread.h繼承Qthread,並在thread.cpp中實現它。
thread.h
#include "QThread" class Thread : public QThread { Q_OBJECT public: Thread(); // void setMessage(const Qstring &message); void setRun(); void stop(); bool getState(); protected: void run(); private: // QString messageStr; volatile bool enable; signals: void OutMessage(QString message); };
thread.cpp,在run函數中循環1秒觸發一個信號輸出信息。
#include "thread.h" Thread::Thread() { enable = true; } void Thread::run() { while(true) { if(enable) { this->OutMessage(tr("I'm run : thread 1")); msleep(1000); } } } void Thread::stop() { enable = false; } void Thread::setRun() { enable = true; } bool Thread::getState() { return enable; }
mainwindow.h,定義一些Qt控件
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QLabel> #include <QGridLayout> #include <QPushButton> #include <QTextEdit> #include <QDoubleValidator> #include <QComboBox> #include <QTranslator> #include "thread.h" #define PI 3.14592653589 class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); ~MainWindow(); private: QWidget* mainWindow; QGridLayout * mainLayout; QTextEdit * messageEdit; QPushButton * clearButton; QPushButton * runStopButton; Thread * backThread; private slots: void updateMessage(QString message); void clearMessage(); void runStopThread(); }; #endif
mainwindow.cpp
#include "mainwindow.h" #include <QPainter> MainWindow :: MainWindow() { mainWindow = new QWidget; this->setCentralWidget(mainWindow); backThread = new Thread(); backThread->start(); clearButton = new QPushButton(tr("clear")); clearButton->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed); runStopButton = new QPushButton(tr("stop")); messageEdit = new QTextEdit(); messageEdit->setReadOnly(true); mainLayout = new QGridLayout; mainLayout->addWidget(messageEdit,0,0,5,5); mainLayout->addWidget(clearButton,1,5,1,1); mainLayout->addWidget(runStopButton,0,5,1,1); mainWindow->setLayout(mainLayout); QObject::connect(clearButton,SIGNAL(clicked()),this,SLOT(clearMessage())); QObject::connect(runStopButton,SIGNAL(clicked()),this,SLOT(runStopThread())); QObject::connect(backThread,SIGNAL(OutMessage(QString)),this,SLOT(updateMessage(QString))); this->setWindowTitle(tr("thread test~")); this->resize(QSize(300,100)); // this->setFixedSize(200,100); } MainWindow :: ~MainWindow() { mainWindow->deleteLater(); mainLayout->deleteLater(); messageEdit->deleteLater(); clearButton->deleteLater(); runStopButton->deleteLater(); } void MainWindow::updateMessage(QString message) { messageEdit->append(message); } void MainWindow::clearMessage() { messageEdit->clear(); } void MainWindow::runStopThread() { if(backThread->getState()) { backThread->stop(); runStopButton->setText(tr("run")); } else { backThread->setRun(); runStopButton->setText(tr("stop")); } }
運行:
后台線程不斷打印信息,通過run/stop按鈕停止/啟動。
同時,Qt提供一套線程同步機制
QMutex(互斥鎖),QReadWriteLock(讀寫鎖),QSemaphore(信號量),QWaitCondition(阻塞等待一個條件)。
使用都很簡單,其中QWaitCondition,調用bool wait(QMutex *mutex, unsigned long time = ULONG_MAX)成員函數阻塞。 void wakeOne()和void wakeAll()喚醒一處和所有阻塞。(類似於C#里面的ManualResetEvent 類,.WaitOne() .Set())