• 7077阅读
  • 5回复

[提问]如何连接多线程中的信号与槽? [复制链接]

上一主题 下一主题
离线tomxue
 
只看楼主 倒序阅读 楼主  发表于: 2012-12-22
The mainwindow.cpp:
  1. #include "ui_mainwindow.h"
  2.     #include <QtCore>
  3.     
  4.     /* ****** Thread part ****** */
  5.     myThread::myThread(QObject *parent)
  6.         : QThread(parent)
  7.     {
  8.     }
  9.     
  10.     void myThread::run()
  11.     {
  12.         while(1){
  13.             qDebug("thread one----------");
  14.             emit threadSignal1();
  15.             usleep(100000);
  16.         }
  17.         exec();
  18.     }
  19.     
  20.     myThread2::myThread2(QObject *parent)
  21.         : QThread(parent)
  22.     {
  23.     }
  24.     
  25.     void myThread2::run()
  26.     {
  27.         while(1){
  28.             qDebug("thread two");
  29.             emit threadSignal2();
  30.             usleep(100000);
  31.         }
  32.         exec();
  33.     }
  34.     MainWindow::MainWindow(QWidget *parent) :
  35.         QMainWindow(parent),
  36.         ui(new Ui::MainWindow)
  37.     {
  38.         ui->setupUi(this);
  39.     
  40.         onethread = new myThread(this);
  41.         onethread->start(QThread::NormalPriority);
  42.     
  43.         twothread = new myThread2(this);
  44.         twothread->start(QThread::NormalPriority);
  45.     
  46.         connect(onethread, SIGNAL(onethread->threadSignal1()),
  47.                 this, SLOT(mySlot1()));
  48.         connect(twothread, SIGNAL(threadSignal2()),
  49.                 this, SLOT(mySlot2()),Qt::QueuedConnection);
  50.     }
  51.     
  52.     void MainWindow::mySlot1()
  53.     {
  54.         ui->textEdit1->append("This is thread1");
  55.     }
  56.     
  57.     void MainWindow::mySlot2()
  58.     {
  59.         ui->textEdit1->append("This is thread2");
  60.     }
  61.     
  62.     MainWindow::~MainWindow()
  63.     {
  64.         delete ui;
  65.     }
  66.     
  67.     void MainWindow::on_pushButton_clicked()
  68.     {
  69.         ui->textEdit1->append("textEdit1");
  70.         ui->textEdit2->append("textEdit2");
  71.     }

The mainwindow.h:
  1. #define MAINWINDOW_H
  2.     
  3.     #include <QMainWindow>
  4.     #include <QThread>
  5.     
  6.     namespace Ui {
  7.     class MainWindow;
  8.     }
  9.     
  10.     class myThread : public QThread
  11.     {
  12.       Q_OBJECT
  13.     
  14.     public:
  15.         myThread(QObject *parent = 0);
  16.         void run();
  17.     
  18.     signals:
  19.         void threadSignal1();
  20.     };
  21.     
  22.     class myThread2 : public QThread
  23.     {
  24.       Q_OBJECT
  25.     
  26.     public:
  27.         myThread2(QObject *parent = 0);
  28.         void run();
  29.     
  30.     signals:
  31.         void threadSignal2();
  32.     };
  33.     
  34.     class MainWindow : public QMainWindow
  35.     {
  36.         Q_OBJECT
  37.     
  38.     public:
  39.         explicit MainWindow(QWidget *parent = 0);
  40.         ~MainWindow();
  41.         void mySlot1();
  42.         void mySlot2();
  43.     
  44.     private slots:
  45.         void on_pushButton_clicked();
  46.     
  47.     private:
  48.         Ui::MainWindow *ui;
  49.         myThread *onethread;
  50.         myThread2 *twothread;
  51.     };
  52.     
  53.     #endif // MAINWINDOW_H





上面的代码qDebug可以给出正确的输出,但是界面上的textEdit没有相应的输出?貌似是跨线程信号与槽调用的问题,请帮忙指出如何解决!谢谢!

社会舞台是人类本身最为广阔的学习源泉
离线XChinux

只看该作者 1楼 发表于: 2012-12-22
你在run()中,一个while()循环,发射了N个信号,但一直没有进入到exec()循环中。
在外面只管connect好信号就好了,在exec()内部再emit
二笔 openSUSE Vim N9 BB10 XChinux@163.com 网易博客 腾讯微博
承接C++/Qt、Qt UI界面、PHP及预算报销系统开发业务
离线roywillow

只看该作者 2楼 发表于: 2012-12-22
我之前实现这种while无限循环是声明了一个槽,在这个槽中执行代码发射信号,并用QTimer::singleShot()调用自己,然后在run()中调用这个槽和exec()
专业维修核潜艇,回收二手航母、二手航天飞机,大修核反应堆,拆洗导弹发动机更换机油,无人侦察机手动挡改自动,航天飞机保养换三滤,飞碟外太空年检 ,各型号导弹加装迎宾踏板,高空作业擦洗卫星表面除尘、打蜡及抛光,东风全系列巡航导弹。并提供原子对撞机。量大从优,有正规发票。
离线hohos

只看该作者 3楼 发表于: 2012-12-23
原理:
http://qt-project.org/wiki/Threads_Events_QObjects_Chinese
示例(需翻墙):
http://codethis.wordpress.com/2011/04/04/using-qthread-without-subclassing/
http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/



如果线程代码很简单,只是一个函数的话,可以用QtConcurrent

简单实现信号和槽的话,可以如上述URL所说,
建立一个QOBJECT对象,而不是继承自QTHREAD
建立QOBJECT和MAINWINDOW与QThread的信号槽连接
然后moveToThread(thread)。
最后thread->start


我的小东东的示例:
https://github.com/sd44/fcitx-table-editor/blob/master/src/MainWindow.cpp
第181行用的moveToThread

109行有个QtConcurrent的示例
QFuture<void> openFuture = QtConcurrent::run(&xx, &FileParser::openFile, fileName);


猜测:
LZ在new了QThread之后,立即建立连接,然后start()可以解决这个问题吗?
离线jdwx

只看该作者 4楼 发表于: 2012-12-23
着重看红色的部分
    class MainWindow : public QMainWindow
    {
        Q_OBJECT

    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
        void mySlot1();
        void mySlot2();


    private slots:
        void on_pushButton_clicked();

    private:
        Ui::MainWindow *ui;
        myThread *onethread;
        myThread2 *twothread;
    };
发帖时要说明:操作系统、Qt版本、编译器,这样能更快的得到回复。
离线jdwx

只看该作者 5楼 发表于: 2012-12-23
信号和槽用于多线程也没有什么区别,还是那么写那么用,只不过信号和槽需要一个反应时间,不要调用的太频繁,两次调用间隔要大于槽的运行时间。
发帖时要说明:操作系统、Qt版本、编译器,这样能更快的得到回复。
快速回复
限100 字节
 
上一个 下一个