• 欢迎浏览“String me = Creater\忠实的资深Linux玩家;”,请文明浏览,理性发言,有侵犯你的权益请邮件我(creater@vip.qq.com).
  • 把任何的失败都当作一次尝试,不要自卑;把所有的成功都想成是一种幸运,不要自傲。
  •    4年前 (2014-04-20)  QT 评论关闭  18 
    文章评分 0 次,平均分 0.0

    Qt线程间共享数据主要有两种方式:
    1.使用共享内存。即使用一个两个线程都能够共享的变量(如全局变量),这样两个线程都能够访问和修改该变量,从而达到共享数据的目的;
    2.使用singal/slot机制,把数据从一个线程传递到另外一个线程。

    第一种办法在各个编程语言都使用普遍,而第二种方式倒是QT的特有方式,下面主要学习一下这种方式:

    在线程之间传递signal与在一个线程内传递signal是不一样的。在一个线程内传递signal时,emit语句会直接调用所有连接的slot并等待到所有slot被处理完;在线程之间传递signal时,slot会被放到队列中(queue),而emit这个signal后会马上返回;默认情况,线程之间使用queue机制,而线程内使用direct机制,但在connect中可以改变这些默认的机制。
    像QString等这些QT本身定义的类型,直接传送即可。但如果是自己定义的类型如果想使用signal/slot来传递的话,则没有这么简单。直接使用的话,会产生下面这种错误:
    QObject::connect: Cannot queue arguments of type 'TextAndNumber' (Make sure 'TextAndNumber' is registed using qRegisterMetaType().)
    原因:当一个signal被放到队列中(queued)时,它的参数(arguments)也会被一起一起放到队列中(queued起来),这就意味着参数在被传送到slot之前需要被拷贝、存储在队列中(queue)中;为了能够在队列中存储这些参数(argument),Qt需要去construct、destruct、copy这些对象,而为了让Qt知道怎样去作这些事情,参数的类型需要使用qRegisterMetaType来注册(如错误提示中的说明)

    步骤:(以自定义TextAndNumber类型为例)

    自定一种类型,在这个类型的顶部包含:#include
    在类型定义完成后,加入声明:Q_DECLARE_METATYPE(TextAndNumber);
    在main()函数中注册这种类型:qRegisterMetaType("TextAndNumber");
    如果还希望使用这种类型的引用,可同样要注册:qRegisterMetaType("TextAndNumber&");

    //TextAndNumber.h
    #ifndef TEXTANDNUMBER_H
    #define TEXTANDNUMBER_H
    #include <QMetaType>
    //必须包含QMetaType,否则会出现下面错误:
    //error: expected constructor, destructor, or type conversion before ‘;’ token
    #include <QString>
    class TextAndNumber {
    public:
        TextAndNumber();
        TextAndNumber(int, QString);
        int count();
        QString text();
    private:
        int m_count;
        QString m_text;
    };
    Q_DECLARE_METATYPE(TextAndNumber);
    #endif // TEXTANDNUMBER_H
    
    //TextAndNumber.cpp
    #include "TextAndNumber.h"
    TextAndNumber::TextAndNumber() {
    }
    TextAndNumber::TextAndNumber(int count, QString text) {
        m_count = count;
        m_text = text;
    }
    int TextAndNumber::count() {
        return m_count;
    }
    QString TextAndNumber::text() {
        return m_text;
    }
    
    //TextDevice.h
    #ifndef TEXTDEVICE_H
    #define TEXTDEVICE_H
    #include <QThread>
    #include <QDebug>
    #include <QString>
    #include "TextAndNumber.h"
    class TextDevice : public QThread {
        Q_OBJECT
    public:
        TextDevice();
        void run();
        void stop();
    public slots:
        void write(TextAndNumber& tran);
    private:
        int m_count;
    };
    
    #endif // TEXTDEVICE_H
    
    //TextDevice.cpp
    #include "TextDevice.h"
    TextDevice::TextDevice() : QThread() {
        m_count = 0;
    }
    void TextDevice::run() {
        exec();
    }
    void TextDevice::stop() {
        quit();
    }
    void TextDevice::write(TextAndNumber& tran) {
        qDebug() << QString("Call %1 (%3): %2").arg(m_count++).arg(tran.text()).arg(tran.count());
    }
    
    //TextThread.h
    #ifndef TEXTTHREAD_H
    #define TEXTTHREAD_H
    #include <QThread>
    #include <QString>
    #include "TextAndNumber.h"
    class TextThread : public QThread {
        Q_OBJECT
    public:
        TextThread(const QString& text);
        void run();
        void stop();
    signals:
        void writeText(TextAndNumber& tran);
    private:
        QString m_text;
        int m_count;
        bool m_stop;
    };
    
    #endif // TEXTTHREAD_H
    
    //TextThread.cpp
    #include "TextThread.h"
    TextThread::TextThread(const QString& text) : QThread() {
        m_text = text;
        m_stop = false;
        m_count = 0;
    }
    void TextThread::run() {
        while(!m_stop) {
            TextAndNumber tn(m_count++, m_text);
            emit writeText(tn);
            sleep(1);
        }
    }
    void TextThread::stop() {
        m_stop = true;
    }
    
    //main.cpp
    #include <QApplication>
    #include <QMessageBox>
    #include "TextThread.h"
    #include "TextDevice.h"
    #include "TextAndNumber.h"
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
        qRegisterMetaType<TextAndNumber>("TextAndNumber");
        qRegisterMetaType<TextAndNumber>("TextAndNumber&");
        TextDevice device;
        TextThread foo("foo"), bar("bar");
        QObject::connect(&foo, SIGNAL(writeText(TextAndNumber&)), &device, SLOT(write(TextAndNumber&)));
        QObject::connect(&bar, SIGNAL(writeText(TextAndNumber&)), &device, SLOT(write(TextAndNumber&)));
        device.start();
        foo.start();
        bar.start();
        QMessageBox::information(0, "Threading", "Click me to close");
    
        foo.stop();
        bar.stop();
        device.stop();
        foo.wait();
        bar.wait();
        device.wait();
        qDebug() << "Application end.";
        return 0;
    }
    
     

    除特别注明外,本站所有文章均为String me = "Creater\忠实的资深Linux玩家";原创,转载请注明出处来自http://unix8.net/home.php/3417.html

    关于
    切换注册

    登录

    忘记密码 ?

    切换登录

    注册

    扫一扫二维码分享