当前位置:   article > 正文

lv20 QT进程线程编程

lv20 QT进程线程编程

知识点:启动进程 ,线程 ,线程同步互斥

1 启动进程

应用场景:通常在qt中打开另一个程序

process模板

  1. QString program =/bin/ls";
  2. QStringList arguments;
  3. arguments << "-l" << “-a";
  4. QProcess *myProcess = new QProcess(parent);
  5. myProcess->execute(program, arguments);

示例:

widget.h

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3. #include <QWidget>
  4. #include <QLineEdit>
  5. #include <QPushButton>
  6. #include <QFileDialog>
  7. #include <QProcess>
  8. #include <QStringList>
  9. class Widget : public QWidget
  10. {
  11. Q_OBJECT
  12. public:
  13. Widget(QWidget *parent = 0);
  14. ~Widget();
  15. public slots:
  16. void showfile()
  17. {
  18. QString filename = QFileDialog::getOpenFileName();
  19. le->setText(filename);
  20. QStringList arg = {filename};
  21. QProcess ppp;
  22. ppp.execute("notepad", arg);
  23. }
  24. private:
  25. QLineEdit *le;
  26. QPushButton *pb;
  27. };
  28. #endif // WIDGET_H

widget.cpp

  1. #include "widget.h"
  2. #include <QVBoxLayout>
  3. Widget::Widget(QWidget *parent)
  4. : QWidget(parent)
  5. {
  6. le = new QLineEdit;
  7. pb = new QPushButton("showtxt");
  8. QVBoxLayout *vbox = new QVBoxLayout;
  9. vbox->addWidget(le);
  10. vbox->addWidget(pb);
  11. setLayout(vbox);
  12. connect(pb, SIGNAL(clicked(bool)), this, SLOT(showfile()));
  13. }
  14. Widget::~Widget()
  15. {
  16. }

效果在qt中使用文本编辑器打开一个文本。 

2 线程

应用场景:启动一个线程和进程来辅助程序

线程:

  1. class WorkerThread : public Qthread{
  2. Q_OBJECT
  3. void run() {
  4. /* ... here is the expensive or blocking operation ... */
  5. emit resultReady(result);
  6. }
  7. signals:
  8. void resultReady(const QString &s);
  9. };
  10. WorkerThread x;
  11. x.start();

  • void run()方法:这是QThread的一个虚函数,你需要在子类中重写它以实现线程的任务。当调用线程的start()方法时,这里的代码将在新的线程中执行。

  • void resultReady(const QString &s)信号:这是一个自定义信号,当线程完成工作并有结果可供返回时,将通过emit关键字发射这个信号。

  • QT是信号驱动、或者异步驱动的框架,平时app需要执行到a.exec()才会执行

 

双线程示例:一个线程打印数组,一个线程排序数组

thread_show.h(继承QThread类)

  1. #ifndef THREAD_SHOW_H
  2. #define THREAD_SHOW_H
  3. #include <Qthread>
  4. #include <QDebug>
  5. #include <QMutex>
  6. class thread_show : public QThread
  7. {
  8. Q_OBJECT
  9. public:
  10. thread_show(char *p):m_arr(p){}
  11. void run() //这是QThread的一个虚函数(qt中斜线表示),你需要在子类中重写它以实现线程的任务。当调用线程的start()方法时,这里的代码将在新的线程中执行。
  12. {
  13. while(1)
  14. {
  15. //lock
  16. qDebug()<<m_arr;
  17. sleep(1);
  18. }
  19. }
  20. private:
  21. char *m_arr;
  22. };
  23. #endif // THREAD_SHOW_H

thread_show.cpp(重写构造函数)

  1. #include "thread_show.h"
  2. /*
  3. thread_show::thread_show()
  4. {
  5. }
  6. */

thread_rev.h

  1. #ifndef THREAD_REV_H
  2. #define THREAD_REV_H
  3. #include <QThread>
  4. class thread_rev : public QThread
  5. {
  6. Q_OBJECT
  7. public:
  8. thread_rev(char *p):m_arr(p){} //构造时,直接赋值效率高
  9. void run()
  10. {
  11. while(1)
  12. {
  13. for(int i=0; i<5; i++)
  14. {
  15. m_arr[i] ^= m_arr[9-i];
  16. m_arr[9-i] ^= m_arr[i];
  17. m_arr[i] ^= m_arr[9-i];
  18. }
  19. }
  20. }
  21. private:
  22. char *m_arr;
  23. };
  24. #endif // THREAD_REV_H

thread_rev.cpp(重写构造函数)

  1. #include "thread_rev.h"
  2. /*
  3. thread_rev::thread_rev()
  4. {
  5. }
  6. */

main.cpp

  1. #include "widget.h"
  2. #include <QApplication>
  3. #include "thread_rev.h"
  4. #include "thread_show.h"
  5. int main(int argc, char *argv[])
  6. {
  7. QApplication a(argc, argv);
  8. char arr[] = "0123456789";
  9. thread_show t1(arr); //打印
  10. thread_rev t2(arr); //翻转数组
  11. t1.start();
  12. t2.start();
  13. return a.exec();
  14. }

 效果:两个线程同时操作,打印出来的数组无规律

 

3 线程互斥

官方示例

  1. QSemaphore :
  2. QSemaphore sem(5); // sem.available() == 5
  3. sem.acquire(3); // sem.available() == 2
  4. sem.acquire(2); // sem.available() == 0
  5. sem.release(5); // sem.available() == 5
  6. sem.release(5); // sem.available() == 10
  7. sem.tryAcquire(1); // sem.available() == 9, returns true
  8. sem.tryAcquire(250); // sem.available() == 9, returns false
  9. QMutex ://locker
  10. QMutex mutex;
  11. void method1(){
  12. mutex.lock();
  13. mutex.unlock();
  14. }
  15. void method2(){
  16. mutex.lock();
  17. mutex.unlock();
  18. }

实验示例:

thread_show.h

  1. #ifndef THREAD_SHOW_H
  2. #define THREAD_SHOW_H
  3. #include <Qthread>
  4. #include <QDebug>
  5. #include <QMutex>
  6. class thread_show : public QThread
  7. {
  8. Q_OBJECT
  9. public:
  10. thread_show(char *p, QMutex *l):m_arr(p), m_arrlock(l){}
  11. void run() //这是QThread的一个虚函数(qt中斜线表示),你需要在子类中重写它以实现线程的任务。当调用线程的start()方法时,这里的代码将在新的线程中执行。
  12. {
  13. while(1)
  14. {
  15. m_arrlock->lock();
  16. qDebug()<<m_arr;
  17. m_arrlock->unlock();
  18. sleep(1);
  19. }
  20. }
  21. private:
  22. char *m_arr;
  23. QMutex *m_arrlock;
  24. };
  25. #endif // THREAD_SHOW_H

thread_show.cpp

  1. #include "thread_show.h"
  2. /*
  3. thread_show::thread_show()
  4. {
  5. }
  6. */

thread_rev.h

  1. #ifndef THREAD_REV_H
  2. #define THREAD_REV_H
  3. #include <QThread>
  4. #include <QMutex>
  5. class thread_rev : public QThread
  6. {
  7. Q_OBJECT
  8. public:
  9. thread_rev(char *p, QMutex *l):m_arr(p), m_arrlock(l){}
  10. void run()
  11. {
  12. while(1)
  13. {
  14. m_arrlock->lock();
  15. for(int i=0; i<5; i++)
  16. {
  17. m_arr[i] ^= m_arr[9-i];
  18. m_arr[9-i] ^= m_arr[i];
  19. m_arr[i] ^= m_arr[9-i];
  20. }
  21. m_arrlock->unlock();
  22. }
  23. }
  24. private:
  25. char *m_arr;
  26. QMutex *m_arrlock;
  27. };
  28. #endif // THREAD_REV_H

thread_rev.cpp

  1. #include "thread_rev.h"
  2. /*
  3. thread_rev::thread_rev()
  4. {
  5. }
  6. */

main.cpp

  1. #include "widget.h"
  2. #include <QApplication>
  3. #include "thread_rev.h"
  4. #include "thread_show.h"
  5. #include <QMutex>
  6. int main(int argc, char *argv[])
  7. {
  8. QApplication a(argc, argv);
  9. char arr[] = "0123456789";
  10. QMutex arr_lock;
  11. thread_show t1(arr,&arr_lock); //打印
  12. thread_rev t2(arr,&arr_lock); //翻转数组
  13. t1.start();
  14. t2.start();
  15. return a.exec();
  16. }

  效果:两个线程同时操作,打印出来的数组均为排序后的结果,排序中不会受到干扰

4 线程同步

目的:实现一个线程获取资源需要等另一个线程释放资源。

thread_hello.h

  1. #ifndef THREAD_HELLO_H
  2. #define THREAD_HELLO_H
  3. #include <QSemaphore>
  4. #include <QThread>
  5. #include <QDebug>
  6. class thread_hello : public QThread
  7. {
  8. Q_OBJECT
  9. public:
  10. thread_hello(QSemaphore *s):sem(s){ }
  11. void run()
  12. {
  13. while(1)
  14. {
  15. qDebug()<<"hello";
  16. sleep(1);
  17. //V
  18. sem->release();
  19. }
  20. }
  21. private:
  22. QSemaphore *sem;
  23. };
  24. #endif // THREAD_HELLO_H

thread_hello.cpp

  1. #include "thread_hello.h"
  2. /*
  3. thread_hello::thread_hello()
  4. {
  5. }
  6. */

thread_world.h

  1. #ifndef THREAD_WORLD_H
  2. #define THREAD_WORLD_H
  3. #include <QThread>
  4. #include <QDebug>
  5. #include <QSemaphore>
  6. class thread_world : public QThread
  7. {
  8. Q_OBJECT
  9. public:
  10. thread_world(QSemaphore *s):sem(s){ }
  11. void run() //字体歪的就是虚函数
  12. {
  13. while(1)
  14. {
  15. //P
  16. sem->acquire();
  17. qDebug()<<"world";
  18. }
  19. }
  20. private:
  21. QSemaphore *sem;
  22. };
  23. #endif // THREAD_WORLD_H

thread_world.cpp

  1. #include "thread_hello.h"
  2. /*
  3. thread_hello::thread_hello()
  4. {
  5. }
  6. */

main.cpp

  1. #include <QCoreApplication>
  2. #include "thread_hello.h"
  3. #include "thread_world.h"
  4. #include <QSemaphore>
  5. int main(int argc, char *argv[])
  6. {
  7. QCoreApplication a(argc, argv);
  8. QSemaphore sem;
  9. thread_hello hello(&sem);
  10. thread_world world(&sem);
  11. hello.start();
  12. world.start();
  13. return a.exec();
  14. }

效果,hello先打印,才会有world。 

 

综合示例:实现两个进度条在下载

mythread1.h

  1. #ifndef MYTHREAD1_H
  2. #define MYTHREAD1_H
  3. #include <QThread>
  4. class myThread1 : public QThread
  5. {
  6. Q_OBJECT
  7. signals:
  8. downloaded(int);
  9. public:
  10. myThread1();
  11. void run()
  12. {
  13. for(int i=0;i<100; i++)
  14. {
  15. //p1->setValue(i);
  16. emit downloaded(i);
  17. QThread::sleep(2);
  18. }
  19. }
  20. };
  21. #endif // MYTHREAD1_H

mythread1.cpp

  1. #include "mythread1.h"
  2. myThread1::myThread1()
  3. {
  4. }

mythread2.h

  1. #ifndef MYTHREAD2_H
  2. #define MYTHREAD2_H
  3. #include <QThread>
  4. class myThread2 : public QThread
  5. {
  6. Q_OBJECT
  7. signals:
  8. downloaded(int);
  9. public:
  10. myThread2();
  11. void run()
  12. {
  13. for(int i=0;i<100; i++)
  14. {
  15. //p1->setValue(i);
  16. emit downloaded(i);
  17. QThread::sleep(1);
  18. }
  19. }
  20. };
  21. #endif // MYTHREAD2_H

mythread1.cpp

  1. #include "mythread2.h"
  2. myThread2::myThread2()
  3. {
  4. }

widget.h

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3. #include <QWidget>
  4. #include <QProgressBar>
  5. #include "mythread2.h"
  6. #include "mythread1.h"
  7. class Widget : public QWidget
  8. {
  9. Q_OBJECT
  10. public:
  11. Widget(QWidget *parent = 0);
  12. ~Widget();
  13. private:
  14. QProgressBar *p1, *p2;
  15. myThread1 *t1;
  16. myThread2 *t2;
  17. };
  18. #endif // WIDGET_H

widget.cpp

  1. #include "widget.h"
  2. #include <QVBoxLayout>
  3. #include <QThread>
  4. Widget::Widget(QWidget *parent)
  5. : QWidget(parent)
  6. {
  7. p1 = new QProgressBar;
  8. p2 = new QProgressBar;
  9. QVBoxLayout *vbox = new QVBoxLayout;
  10. vbox->addWidget(p1);
  11. vbox->addWidget(p2);
  12. setLayout(vbox);
  13. t1 = new myThread1;
  14. t2 = new myThread2;
  15. connect(t1, SIGNAL(downloaded(int)), p1, SLOT(setValue(int)));
  16. connect(t2, SIGNAL(downloaded(int)), p2, SLOT(setValue(int)));
  17. t1->start();
  18. t2->start();
  19. #if 0
  20. for(int i=0;i<100; i++)
  21. {
  22. p1->setValue(i);
  23. QThread::sleep(1);
  24. }
  25. for(int i=0;i<100; i++)
  26. {
  27. p2->setValue(i);
  28. QThread::sleep(2);
  29. }
  30. #endif
  31. }
  32. Widget::~Widget()
  33. {
  34. }

注:

downloaded(不需要实现,qt实现的不是函数)

emit发送一个信号

exit 发送信号

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号