跨线程的Qt信号,一个是GUI线程? [英] Qt signaling across threads, one is GUI thread?

查看:71
本文介绍了跨线程的Qt信号,一个是GUI线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Qt 中使用 moveToThread 将对象从一个线程移动到另一个线程是什么意思?甚至在使用 moveToThread 之前,一切似乎都可以工作,它将对象从一个线程(GUI 线程)移动到另一个线程(工作)并且 Qt:connect 调用对象上的适当插槽.

What does it mean to move a object from one thread to another in Qt using moveToThread? Everything seems to work even before using moveToThread, which moves the object from one thread (GUI thread) to a another thread ( worked) and Qt:connect calls the appropriate slot on object.

对象所在的位置,GUI 线程或工作线程有什么区别吗?

Is there any difference because of where the object lives, GUI thread or the worker thread?

我做了一个小程序,但我不明白QThread是如何与Signal和slot函数一起工作的,如果你能用例子解释moveToThread的用途,我将不胜感激

I made a small program, but I don't understand how QThread works along with Signal and slot function, I would appreciate if you could explain what is the use of moveToThread with the example

#include <QtGui/QApplication>
#include <QPushButton>
#include <QHBoxLayout>
#include <QLineEdit>
#include <QString>
#include "mythread.h"
//GUI calls a thread to do some job and sub update the text box once it is done
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    QHBoxLayout * pH = new QHBoxLayout(&w);
    QPushButton * pushButton = new QPushButton("asdad");
    QLineEdit * lineEdit = new QLineEdit("AAA");
    pH->addWidget(pushButton);
    pH->addWidget(lineEdit);
    w.setLayout(pH);
    w.show();
    MyThread thread;
    qDebug("Thread id %d",(int)QThread::currentThreadId());
    QObject::connect(pushButton,SIGNAL(clicked()),&thread,SLOT(callRun())) ;
    QObject::connect(&thread,SIGNAL(signalGUI(QString)),lineEdit,SLOT(setText(QString)));
    return a.exec();
}

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>
#include <QMutex>

class MyThread : public QThread
{
    Q_OBJECT
public:
    MyThread();
public slots:
    void callRun();
    void run();
 signals:
    void signalGUI(QString);
private:
    QMutex mutex;

};

#endif // MYTHREAD_H


#include "mythread.h"
#include <QDebug>
#include <QString>
#include <QMutexLocker>

MyThread::MyThread()
{
}
 void MyThread::callRun()
 {

     qDebug("in thread");
    if(!isRunning())
     {
        this->start(LowestPriority);
        exec();
    }
    else
    {
        run();
    }

 }
 void MyThread::run()
 {
     QMutexLocker fn_scope(&mutex);
     static int a = 0;
    ++a;
     qDebug("Thread id inside run %d",(int)QThread::currentThreadId());
     this->sleep(3);
     static QString number;
     QString temp;
     number += temp.setNum(a);
     emit signalGUI(number);
 }

推荐答案

看一看 跨线程的信号和插槽.如果您总是使用信号和槽来与工作线程通信,Qt 会在需要时为您处理 moveToThread,并且您使用了正确的连接.

Take a look at Signals and slots across threads. If you always use signals and slots to communicate with the worker thread, Qt handles the moveToThread for you if it's needed and you used the correct connection.

我猜这篇文章的作者是看到了他的问题,因为他在实际创建线程之前在构造函数中调用了 start .换句话说,不要盲目相信第三方代码.

I would guess the article's author was seeing his problem since he was calling start in the constructor before the thread was actually created. In other words, don't trust third-party code blindly.

为了回应您的评论,请查看 Mandelbrot 示例,在 MandelbrotWidget Class Implementation 标题下:

In response to your comment, look at the Mandelbrot example, under the MandelbrotWidget Class Implementation header:

对于排队连接,Qt 必须存储传递给信号的参数的副本,以便稍后将它们传递到插槽.Qt 知道如何复制许多 C++ 和 Qt 类型,但 QImage 不是其中之一.因此,我们必须先调用模板函数 qRegisterMetaType(),然后才能在排队连接中使用 QImage 作为参数.

With queued connections, Qt must store a copy of the arguments that were passed to the signal so that it can pass them to the slot later on. Qt knows how to take of copy of many C++ and Qt types, but QImage isn't one of them. We must therefore call the template function qRegisterMetaType() before we can use QImage as parameter in queued connections.

我认为这有点过时了,这里是 有效的元类型.由于跨线程的信号和槽使用排队连接,因此在大多数情况下您不必执行 moveToThread 调用.

I believe this is slightly outdated, here are the valid meta types. Since signals and slots across threads use queued connections, you should not have to do the moveToThread calls in most cases.

我会尝试用一个类似的例子来解释:

I will try to explain things with a similar example:

mythread.h:

mythread.h:

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>
#include <QMutex>

class MyThread : public QThread
{
   Q_OBJECT

protected:
   virtual void run();

signals:
   void signalGUI(QString);
};

#endif // MYTHREAD_H

mythread.cpp:

mythread.cpp:

#include "mythread.h"
#include <QString>

void MyThread::run()
{
   qDebug("Thread id inside run %d",(int)QThread::currentThreadId());
   static int run = 0;
   QString temp = QString("Run: %1").arg(run++);
   qDebug("String address inside run %p", &temp);
   emit signalGUI(temp);
}

mylineedit.h

mylineedit.h

#ifndef MYLINEEDIT_H
#define MYLINEEDIT_H

#include <QLineEdit>

class MyLineEdit : public QLineEdit
{
Q_OBJECT
public:
    explicit MyLineEdit(QWidget *parent = 0);

public slots:
    void setText(const QString &string);

};

#endif // MYLINEEDIT_H

mylineedit.cpp

mylineedit.cpp

#include "mylineedit.h"
#include <QThread>

MyLineEdit::MyLineEdit(QWidget *parent) :
    QLineEdit(parent)
{
}

void MyLineEdit::setText(const QString &string)
{
   qDebug("Thread id inside setText %d",(int)QThread::currentThreadId());
   qDebug("String address inside setText %p\n", &string);
   QLineEdit::setText(string);
}

main.cpp:

#include <QApplication>
#include <QPushButton>
#include <QHBoxLayout>
#include "mythread.h"
#include "mylineedit.h"

//GUI calls a thread to do some job and sub update the text box once it is done
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
   QWidget w;
   QHBoxLayout * pH = new QHBoxLayout(&w);
   QPushButton * pushButton = new QPushButton("Run Thread", &w);
   MyLineEdit * lineEdit = new MyLineEdit(&w);

   pH->addWidget(pushButton);
   pH->addWidget(lineEdit);
   w.show();

   MyThread thread;
   qDebug("Thread id %d",(int)QThread::currentThreadId());
   QObject::connect(pushButton,SIGNAL(clicked()),&thread,SLOT(start())) ;
   QObject::connect(&thread,SIGNAL(signalGUI(const QString&)),lineEdit,SLOT(setText(const QString&)));
   return a.exec();
}

点击按钮后的示例输出:

Sample output after clicking button:

Thread id 1088110320
Thread id inside run 1093176208
String address inside run 0x41288350
Thread id inside setText 1088110320
String address inside setText 0x974af58

如您所见,运行线程与主 GUI 线程不同.此外,即使您传递了对 QString 的 const 引用,由于它跨越了线程边界,因此它会复制它.我强烈鼓励您阅读线程和QObject.

As you can see, the run thread is different than the main GUI thread. Also, even though you pass a const reference to a QString, since it crosses thread boundaries it copies it. I strongly encourage you to read Threads and QObject.

这篇关于跨线程的Qt信号,一个是GUI线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆