Qt QThread 執行緒建立,執行緒同步,執行緒通訊 例項
阿新 • • 發佈:2019-01-30
1. 繼承QThread, 實現run()方法, 即可建立執行緒。
2. 例項1 程式碼
myThread.h
#ifndef MYTHREAD_H #define MYTHREAD_H #include <QThread> class myThread : public QThread //myThread 執行緒類 { Q_OBJECT public: myThread(); void setMessage(const QString &message); void stop(); protected: void run(); //複寫run()方法,裡面是執行緒 的 主體程式碼 private: QString messageStr; volatile bool stopped; }; #endif // MYTHREAD_H
myThread.cpp
#include "myThread.h" #include <QDebug> myThread::myThread() { stopped = false; } void myThread::run() //實現run()方法, 隔1秒輸出messageStr { while(!stopped) { qDebug() << messageStr << endl; sleep(1); } stopped = false; } void myThread::stop() { stopped = true; } void myThread::setMessage(const QString &message) { messageStr = message; }
dialog.h
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QtGui> #include "myThread.h" class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); ~Dialog(); protected: void closeEvent(QCloseEvent *event); private slots: void startOrStopThreadA(); void startOrStopThreadB(); private: myThread threadA; //用執行緒類 例項化 執行緒物件 myThread threadB; QPushButton *threadAButton; QPushButton *threadBButton; QPushButton *quitButton; }; #endif // DIALOG_H
dialog.cpp
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
threadA.setMessage("A");
threadB.setMessage("B");
threadAButton = new QPushButton(tr("Start A"));
threadBButton = new QPushButton(tr("Start B"));
quitButton = new QPushButton(tr("Quit"));
quitButton->setDefault(true);
connect(threadAButton, SIGNAL(clicked()), this, SLOT(startOrStopThreadA()));
connect(threadBButton, SIGNAL(clicked()), this, SLOT(startOrStopThreadB()));
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
QHBoxLayout *hLayout = new QHBoxLayout;
hLayout->addWidget(threadAButton);
hLayout->addWidget(threadBButton);
hLayout->addWidget(quitButton);
setLayout(hLayout);
}
Dialog::~Dialog()
{
}
void Dialog::startOrStopThreadA()
{
if( threadA.isRunning() )
{
threadA.stop(); //結束執行緒
threadAButton->setText(tr("Start A"));
}
else
{
threadA.start(); //thread.start()開始執行緒
threadAButton->setText(tr("Stop A"));
}
}
void Dialog::startOrStopThreadB()
{
if( threadB.isRunning() )
{
threadB.stop();
threadBButton->setText(tr("Start B"));
}
else
{
threadB.start();
threadBButton->setText(tr("Stop B"));
}
}
void Dialog::closeEvent(QCloseEvent *event) //當用戶點選quit按鍵 或 這退出UI的時候,回撥closeEvent函式
{
threadA.stop();
threadB.stop();
threadA.wait();
threadB.wait();
event->accept();
//qDebug("--log--");
}
3. 執行緒同步
QT執行緒同步的類有: QMutex, QReadWriteLock, QSemaphore, QWaitcondition.
QMutext互斥鎖: 可以鎖住一段程式碼,同一時間只能有一個執行緒訪問。
或者用簡化鎖QMutexLocked類, 建構函式輸入QMutex並將其鎖住, 解構函式將其解鎖。
QReadWriteLock類, 允許多個執行緒讀共享資源,但是隻允許一個執行緒寫共享資源。
QSemaphore 訊號量 互斥量, 解決 生產者--消費者 問題
4. 利用訊號槽, 主執行緒和子執行緒通訊,互相傳送訊息。
子執行緒向主執行緒傳送 每隔一秒向主執行緒傳送累加數字, 主執行緒按鍵資訊傳送到子執行緒。。
Thread.h
#ifndef THREAD_H
#define THREAD_H
#include <QThread>
class Thread : public QThread
{
Q_OBJECT
private:
int number;
protected:
void run();
public:
Thread(QObject *parent=0);
~Thread();
signals:
void UpdateSignal(int num);
public slots:
void ResetSlot();
};
#endif // THREAD_H
Thread.cpp
#include "Thread.h"
Thread::Thread(QObject *parent)
{
number = 0;
}
Thread::~Thread()
{
}
void Thread::run()
{
while(1)
{
emit UpdateSignal(number); //傳送更新訊號給主執行緒,附帶引數number
number++;
sleep(1);
}
}
void Thread::ResetSlot()
{
number = 0;
emit UpdateSignal(number); //傳送重置number訊號
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QtGui>
#include "Thread.h"
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
private:
QLabel *label;
QPushButton *startButton;
QPushButton *stopButton;
QPushButton *resetButton;
Thread *myThread;
int number;
signals:
void ResetSignal();
public slots:
void clearSlot();
void startSlot();
void stopSlot();
void updateSlot(int num);
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
startButton = new QPushButton("start");
stopButton = new QPushButton("stop");
resetButton = new QPushButton("reset");
label = new QLabel("empty");
myThread = new Thread();
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(label);
layout->addWidget(startButton);
layout->addWidget(stopButton);
layout->addWidget(resetButton);
setLayout(layout);
connect(stopButton, SIGNAL(clicked()), this, SLOT(stopSlot()));
connect(startButton, SIGNAL(clicked()), this, SLOT(startSlot()));
connect(resetButton, SIGNAL(clicked()), this, SLOT(clearSlot()));
connect(myThread, SIGNAL(UpdateSignal(int)), this, SLOT(updateSlot(int))); //子執行緒發訊號給主執行緒,更新number
connect(this, SIGNAL(ResetSignal()), myThread, SLOT(ResetSlot())); //主執行緒發訊號給子執行緒,重置number訊號
resize(200, 200);
}
Widget::~Widget()
{
}
void Widget::startSlot()
{
myThread->start();
}
void Widget::stopSlot()
{
myThread->terminate();
}
void Widget::updateSlot(int num)
{
label->setText(QString::number(num));
}
void Widget::clearSlot()
{
emit ResetSignal(); //主執行緒傳送重置訊號 給 子執行緒
}