这时候就足以在脚下的应用程序中调用外部的程序来促成该意义,创制步骤如下

QT中使用线程能够增加工效。

该小说原创于Qter开源社区(www.qter.org),小编yafeilinux,转发请声明出处!

要利用线程要通过一下八个步骤:

导语

(一)先成立3个c++ class文件,记得继承Thread,创制步骤如下:


          a、第一步

在前面包车型客车几节内容中等教育授了Qt互连网编制程序的部分主导内容,这1节来看一下在Qt中经过和线程的宗旨使用。

        图片 1

 

        b、第二步

 

         图片 2

 

 

环境:Windows Xp + Qt 4.8.5+Qt Creator2.8.0

                 图片 3

目录

 


(二)自定义1个run函数,今后运维线程的时候,程序就会跳转到run函数中

一、进程

void run();

二、线程

(三)起首化线程

正文

HDThread mythread = new HDThread();

(4)运转线程

 

mythread->start();

一、进程

 

 

下边来看望线程使用的有血有肉列子:

 
  在统筹三个应用程序时,有时不愿意将八个不太相关的成效集成到程序中,恐怕是因为该效用与当前设计的应用程序联系十分小,或许是因为该成效已经得以使用现成的先后很好的兑现了,那时就足以在当前的应用程序中调用外部的次第来兑现该意义,那就会选拔到进度。Qt应用程序能够很简单的起步2个表面应用程序,而且Qt也提供了在四种经过间通讯的章程。

线程头文件hdthread.h:

   
Qt的QProcess类用来运转二个外表程序并与其实行通讯。上面我们来看一下怎么在Qt代码中运维二个经过。

 1 #ifndef HDTHREAD_H
 2 #define HDTHREAD_H
 3 #include <QThread>
 4 #include <QLabel>
 5 #include <QMutex>
 6 
 7 class HDTHread : public QThread
 8 {
 9 public:
10     HDTHread(QMutex* mtex,QObject *parent = 0);
11     void run();//自定义的run函数
12     void setLabel(QLabel *lb);
13 private:
14     QLabel *label;
15     QMutex *mutex; //互斥锁
16 };
17 
18 #endif // HDTHREAD_H

 

主函数的头文件threadqt.h

 

 1 #ifndef THREADQT_H
 2 #define THREADQT_H
 3 
 4 #include <QMainWindow>
 5 #include <hdthread.h>
 6 #include <writefile.h>
 7 #include <QMutex>
 8 #include <QSemaphore>
 9 
10 namespace Ui {
11 class ThreadQt;
12 }
13 
14 class ThreadQt : public QMainWindow
15 {
16     Q_OBJECT
17 
18 public:
19     explicit ThreadQt(QWidget *parent = 0);
20     ~ThreadQt();
21 
22      //定义静态的信号类
23     static QSemaphore *sp_A;
24     static QSemaphore *sp_B;
25 private slots:
26     void on_pushButton_clicked();
27 
28 private:
29     Ui::ThreadQt *ui;
30 
31     HDTHread *thread; //hdtread类,里面继承了线程
32     WriteFile *writethread;
33     QMutex mutex;//定义互斥锁类
34 
35 };
36 
37 #endif // THREADQT_H

1.第三创设QtGui应用。

 

工程名字为“myProcess”,别的选项保持暗中认可即可。

 

 

源文件hdthread.cpp:

 

#include "hdthread.h"
#include <QDebug>
#include <threadqt.h>
HDTHread::HDTHread(QMutex *mtex, QObject *parent):QThread(parent)//构造函数,用来初始化
{
    this->mutex = mtex;
}
void HDTHread::setLabel(QLabel *lb)
{
    this->label = lb;
}

void HDTHread::run() //启动线程时执行的函数
{
    while(true)
    {

        qint64 data = qrand()%1000; //取随机数
        //this->mutex->lock();//上锁
        ThreadQt::sp_A->acquire();//请求信号
        this->label->setText(QString::number(data));
         sleep(1);
        ThreadQt::sp_B->release();//释放信号
        //this->mutex->unlock();//解锁

        qDebug()<<"hello Qt"<<data;
    }
}

二.然后规划界面。

源文件threadqt.cpp

在设计方式往界面上拖入一个Push
Button部件,修改其出示文本为“运营多少个进程”。

#include "threadqt.h"
#include "ui_threadqt.h"

//初始化静态变量
 QSemaphore *ThreadQt::sp_A = NULL;
 QSemaphore *ThreadQt::sp_B = NULL;

ThreadQt::ThreadQt(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::ThreadQt)
{
    ui->setupUi(this);
    //创建信号对象
    sp_A = new QSemaphore(1);
    sp_B = new QSemaphore(0);

}

ThreadQt::~ThreadQt()
{
    delete ui;
}

void ThreadQt::on_pushButton_clicked()
{
    thread = new HDTHread(&mutex); //初始化线程
    thread->setLabel(ui->label);
    thread->start();//开启线程

    writethread = new WriteFile(&mutex);
    writethread->setLabel(ui->label);
    writethread->start();
}

 

 

 

我们也看出了,此处的线程也运用了互斥锁(数字信号量)保障线程读写多少时不出新谬误,那里大家可以看一下实际达成的代码

3.修改槽。

this->mutex->lock();//上锁
ThreadQt::sp_A->acquire();//请求信号
this->label->setText(QString::number(data));
sleep(1);
ThreadQt::sp_B->release();//释放信号
this->mutex->unlock();//解锁

在按钮上点击鼠标右键,转到其clicked()信号对应的槽,更改如下:

 

void MainWindow::on_pushButton_clicked()

{

     myProcess.start(“notepad.exe”);

}

 

 

4.进来mainwindow.h文件添加代码。

先添加头文件包涵:#include
<QProcess>,然后添加个人对象定义:QProcess myProcess;

 

 

5.运行程序。

当单击界面上的按钮时就会弹出二个记事本程序。

 

 

此处大家使用QProcess对象运行了Windows系统下的记事本程序(即notepad.exe程序),因为该程序在系统目录中,所以那里不供给钦点其路径。大家也能够运作别的任何的先后,只需求内定其具体路线即可。大家看看,可以运用start()来运维1个程序,有时运转一个顺序时索要钦点运行参数,那种气象在命令行运转程序时是很普遍的,下边来看3个事例,还在面前的例子的基础上实行变更。

 

 

一.在mainwindow.h文件中添加代码。

加上私有槽:

private slots:

    void showResult();

 

 

贰.在mainwindow.cpp文件中添加代码。

 

 

(一)先添加头文件包罗:#include
<QDebug>,然后在构造函数中添加如下代码:

connect(&myProcess,SIGNAL(readyRead()), this, SLOT(showResult()));

 

 

(二)然后添加showResult()槽的概念:

void MainWindow::showResult()

{

    qDebug() << “showResult: ” << endl

            << QString(myProcess.readAll());

}

 

 

(三)最后将日前按钮的单击功率信号对应的槽更改为:

void MainWindow::on_pushButton_clicked()

{

    QString program = “cmd.exe”;

    QStringList arguments;

    arguments << “/c dir&pause”;

    myProcess.start(program, arguments);

}

 
  那里在起步Windows下的命令行提示符程序cmd.exe时为其提供了指令作为参数,那样能够直接执行该命令。当命令执行完之后能够进行showResult()槽来展现运转的结果。那里为了能够显得结果中的普通话字符,使用了QString()进行编码转换。这亟需在mian()函数中添加代码。

 

 

三. 为了保险能够体现输出的中文字符,在main.cpp文件中添加代码。

先添加头文件包括#include
<QTextCodec>,然后在main()函数第一行代码下边,添加如下壹行代码:

QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());

 

 

四.运作程序。

 

按下界面上的按钮,会在Qt Creator中的应用程序输出栏中输出命令的推行结果。

 

 
  对于Qt中经过进一步的选取能够参见QProcess类的辅助文书档案。在Qt中还提供了种种进度间通讯的不二等秘书诀,大家能够在Qt援救中查阅Inter-ProcessCommunication
in Qt关键字对应的文书档案。

 

 

二、线程

 

   

Qt提供了对线程的协理,那包含一组与平台非亲非故的线程类,2个线程安全的出殡事件的艺术,以及跨线程的时限信号-槽的关联。那些使得能够很不难的付出可移植的八线程Qt应用程序,能够丰裕利用多处理器的机械。10二线程编制程序也得以使得的消除在不冻结叁个应用程序的用户界面包车型客车事态下实行二个耗时的操作的题材。关于线程的剧情,大家能够在Qt扶助中参阅Thread
Support in Qt关键字。

 

 

(一)运维叁个线程

 

   
Qt中的QThread类提供了平台无关的线程。3个QThread代表了一个在应用程序中能够独立操纵的线程,它与经过中的其余线程分享数据,不过是独立执行的。相对于一般的主次皆以从main()函数早先实行,QThread从run()函数开端推行。暗中同意的,run()通过调用exec()来拉开事件循环。要创制三个线程,要求子类化QThread并且重新达成run()函数。

 
  每三个线程能够有协调的风浪循环,能够透过调用exec()函数来运营事件循环,能够因而调用exit()或许quit()来终止事件循环。在一个线程中颇具贰个事变循环,能够使它能够关联其余线程中的非确定性信号到本线程的槽上,这使用了队列关联机制,正是在使用connect()函数进行确定性信号和槽的涉及时,将Qt::ConnectionType类型的参数钦定为Qt::QueuedConnection。拥有事件循环还能够使该线程能过使用要求事件循环的类,比如Q提姆er和QTcpSocket类等。注意,在线程中是力不从心利用其它的构件类的。

 
  下边来看多个在图形界面程序中运维多少个线程的例证,在界面上有三个按钮,二个用于开启1个线程,三个用于关闭该线程。

 

 

一.创造项目。

    新建Qt Gui应用,名为“myThread”,类名叫“Dialog”,基类选用QDialog。

 

 

二.设计界面。

    完结项目创设后进入设计形式,向界面中放入四个Push
Button按钮,将首个按钮的突显文本更改为“运维线程”,将其objectName属性更改为startButton;将第3个按钮的显得文本更改为“终止线程”,将其objectName属性更改为stopButton,将其enabled属性废除选中。

 

 

三.添加自定义线程类。

 
  向品种中添加新的C++类,类名设置为“MyThread”,基类设置为“QThread”,类型消息选取“继承自QObject”。达成后进入mythread.h文件,先添加二个国有函数申明:

void stop();

下一场再添加3个函数证明和七个变量的定义:

protected:

    void run();

private:

    volatile bool stopped;

 
  那里stopped变量使用了volatile关键字,这样能够使它在其余时候都维持最新的值,从而可防止止在多个线程中走访它时出错。然后进入mythread.cpp文件中,先添加头文件#include
<QDebug>,然后在构造函数中添加如下代码:

stopped = false;

    那里将stopped变量先导化为false。下边添加run()函数的概念:

void MyThread::run()

{

    qreal i = 0;

    while (!stopped)

        qDebug() << QString(“in MyThread: %1”).arg(i++);

    stopped = false;

}

 
  那里平昔判断stopped变量的值,只要它为false,那么就一向打字与印刷字符串。上边添加stop()函数的定义:

void MyThread::stop()

{

    stopped = true;

}

 
  在stop()函数中将stopped变量设置为了true,那样便足以甘休run()函数中的循环,从而从run()函数中脱离,那样任何线程也就驾鹤归西了。那里运用了stopped变量来促成了经过的告一段落,并从未使用危险的terminate()函数。

 

 

四.在Dialog类中运用自定义的线程。

先到dialog.h文件中,添加头文件包罗:

#include “mythread.h”

    然后添加个人对象的定义:

MyThread thread;

   

下边到设计格局,分别进入五个按钮的单击时域信号对应的槽,更改如下:

 

// 运转线程按钮

void Dialog::on_startButton_clicked()

{

    thread.start();

    ui->startButton->setEnabled(false);

    ui->stopButton->setEnabled(true);

}

 

// 终止线程按钮

void Dialog::on_stopButton_clicked()

{

    if (thread.isRunning()) {

        thread.stop();

        ui->startButton->setEnabled(true);

        ui->stopButton->setEnabled(false);

    }

}

 
  在开发银行线程时调用了start()函数,然后设置了四个按钮的气象。在悬停线程时,先使用isRunning()来判断线程是不是在运营,倘若是,则调用stop()函数来终止线程,并且更改五个按钮的景况。今后运作程序,按下“运行线程”按钮,查看应用程序输出栏的输出,然后再按下“终止线程”按钮,可以看来已经告一段落输出了。

 
  上边大家随后来优化这几个顺序,通过频域信号和槽来将子线程中的字符串展现到主界面上。

 

 

一.在mythread.h文件中添加非信号的概念:

signals:

void stringChanged(const QString &);

 

 

二.然后到mythread.cpp文件中更改run()函数的概念:

void MyThread::run()

{

    long int i = 0;

    while (!stopped) {

       QString str = QString(“in MyThread: %1”).arg(i);

       emit stringChanged(str);

       msleep(1000);

       i++;

    }

    stopped = false;

}

此间每隔一秒就发射二遍功率信号,里面富含了扭转的字符串。

 

 

三.到dialog.h文件中添加槽宣示:

private slots:

    void changeString(const QString &);

 

 

四.开拓dialog.ui,然后向主界面上拖入二个Label标签部件。

 

 

5.到dialog.cpp文件中,在构造函数里面添加非实信号和槽的关系:

// 关联线程中的时限信号和本类中的槽

connect(&thread, SIGNAL(stringChanged(QString)),

this, SLOT(changeString(QString)));

 

 

陆.然后添加槽的概念:

void Dialog::changeString(const QString &str)

{

    ui->label->setText(str);

}

 
  那里就是将子线程发送过来的字符串展现到主界面上。今后能够运作程序,查看效果了。

 

 

(2)线程同步

 

   
Qt中的QMutex、QReadWriteLock、QSemaphore和QWaitCondition类提供了联合线程的艺术。固然使用线程的思想是三个线程能够尽量的出现执行,可是总有1对每天,一些线程必须终止来等待其余线程。例如,假使四个线程尝试同时做客同1的全局变量,结果平日是不分明的。QMutex提供了1个互斥锁(mutex);QReadWriteLock即读-写锁;QSemaphore即随机信号量;QWaitCondition即规范变量。

 

 

(三)可重入与线程安全

 

在翻看Qt的帮忙文书档案时,在许多类的发端都写着“All functions in this class
are reentrant”,大概“All functions in this class are
thread-safe”。在Qt文档中,术语“可重入(reentrant)”和“线程安全(thread-safe)”用来标记类和函数,来注脚怎么着在八线程应用程序中运用它们:

  • 二个线程安全的函数能够同时被多少个线程调用,即正是这几个调用使用了共享数据。因为该共享数据的兼具实例都被体系化了。
  • 3个可重入的函数也得以而且被多少个线程调用,但是只可以是在各种调用使用本人的数码时。

 

 

 

结语


 

最后要注意的是,使用线程是很不难出现难点的,比如无法在主线程以外的线程中应用GUI类的难点(能够差不多的通过如此的艺术来化解:将部分老大耗费时间的操作放在七个独自的干活线程中来进展,等该工作线程实现后将结果再次来到给主线程,最终由主线程将结果突显到显示屏上)。大家应该当心的使用线程。

 

 

http://blog.csdn.net/an505479313/article/details/48494901

相关文章

网站地图xml地图