User interface Qt跨线程信令,一个是GUI线程?

User interface Qt跨线程信令,一个是GUI线程?,user-interface,qt,signals-slots,qthread,User Interface,Qt,Signals Slots,Qthread,在Qt中使用moveToThread将对象从一个线程移动到另一个线程意味着什么?甚至在使用moveToThread之前,一切似乎都正常工作,moveToThread将对象从一个线程(GUI线程)移动到另一个线程(已工作),Qt:connect调用对象上的相应插槽 由于对象所在的位置、GUI线程或工作线程,是否存在任何差异 编辑: 我制作了一个小程序,但我不明白QThread如何与Signal和slot函数一起工作,如果您能用这个示例解释moveToThread的用法,我将不胜感激 #includ

在Qt中使用moveToThread将对象从一个线程移动到另一个线程意味着什么?甚至在使用moveToThread之前,一切似乎都正常工作,moveToThread将对象从一个线程(GUI线程)移动到另一个线程(已工作),Qt:connect调用对象上的相应插槽

由于对象所在的位置、GUI线程或工作线程,是否存在任何差异

编辑: 我制作了一个小程序,但我不明白QThread如何与Signal和slot函数一起工作,如果您能用这个示例解释moveToThread的用法,我将不胜感激

#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);
 }
#包括
#包括
#包括
#包括
#包括
#包括“mythread.h”
//GUI调用一个线程来完成一些工作,并在完成后对文本框进行子更新
int main(int argc,char*argv[])
{
质量保证申请a(argc、argv);
qw;
QHBoxLayout*pH=新的QHBoxLayout(&w);
QPushButton*按钮=新的QPushButton(“asdad”);
QLineEdit*lineEdit=新的QLineEdit(“AAA”);
pH->addWidget(按钮);
pH->addWidget(lineEdit);
w、 设置布局(pH);
w、 show();
神话阅读线程;
qDebug(“线程id%d”,(int)QThread::currentThreadId());
QObject::connect(按钮、信号(单击())、线程、插槽(callRun());
QObject::connect(&thread,SIGNAL(signalGUI(QString)),lineEdit,SLOT(setText(QString)));
返回a.exec();
}
#ifndef MYTHREAD_H
#定义MYTHREAD_H
#包括
#包括
类MyThread:publicqthread
{
Q_对象
公众:
神话阅读();
公众时段:
void callRun();
无效运行();
信号:
void signalGUI(QString);
私人:
QMutex互斥;
};
#endif//MYTHREAD\H
#包括“mythread.h”
#包括
#包括
#包括
MyThread::MyThread()
{
}
void MyThread::callRun()
{
qDebug(“螺纹中”);
如果(!isRunning())
{
此->开始(最低优先级);
exec();
}
其他的
{
run();
}
}
void MyThread::run()
{
QMutexLocker fn_作用域(&mutex);
静态int a=0;
++a;
qDebug(“运行%d内的线程id”,(int)QThread::currentThreadId());
这->睡眠(3);
静态QString数;
管柱温度;
编号+=温度设置编号(a);
发射信号GUI(数字);
}

在线程之间移动对象时,您可以决定它属于哪个事件循环。在线程内建立连接时,信令代码直接调用每个插槽(必须等待它们完成)。跨线程边界的信令将信号调用放在事件循环上,让插槽的线程在准备就绪时调用插槽

在线程之间进行直接调用需要确保函数是可重入的。您还必须确保使用互斥量或信号量保护数据,同时避免竞争条件

在这篇文章中,我猜延迟是由于呼叫是直接的,即根本没有在后台处理(但我只浏览了文本)。

看一看。如果您总是使用信号和插槽与工作线程通信,那么如果需要并且使用了正确的连接,Qt将为您处理moveToThread

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

编辑:为了回应您的评论,请查看
MandelbrotWidget类实现
标题下的示例:

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

我认为这有点过时了,这里是最新的。由于线程之间的信号和插槽使用排队连接,因此在大多数情况下不必执行moveToThread调用

编辑: 我将尝试用一个类似的例子来解释:

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
\ifndef MYTHREAD\u H
#定义MYTHREAD_H
#包括
#包括
类MyThread:publicqthread
{
Q_对象
受保护的:
虚空运行();
信号:
void signalGUI(QString);
};
#endif//MYTHREAD\H
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);
}
#包括“mythread.h”
#包括
void MyThread::run()
{
qDebug(“运行%d内的线程id”,(int)QThread::currentThreadId());
静态int运行=0;
QString temp=QString(“运行:%1”).arg(运行++);
qDebug(“运行%p内的字符串地址,&temp”);
发射信号GUI(温度);
}
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
\ifndef MYLINEEDIT\u H
#定义MYLINEEDIT\u H
#包括
类MyLineEdit:公共QLineEdit
{
Q_对象
公众:
显式MyLineEdit(QWidget*parent=0);
公众时段:
void setText(常量QString和string);
};
#endif//MYLINEEDIT\u H
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);
}
#包括“mylineedit.h”
#包括
MyLineEdit::MyLineEdit(QWidget*父项):
QLineEdit(父级)
{
}
void MyLineEdit::setText(常量QString&string)
{
qDebug(“setText%d内的线程id”,(int)QThread::currentThreadId());
qDebug(“setText%p\n中的字符串地址,&String”);
QLineEdit::setText(字符串);
}
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();
}
#包括
#包括
#包括
#包括“mythread.h”
#包括“mylineedit.h”
//GUI调用一个线程来完成一些工作,并在完成后对文本框进行子更新
int main(int argc,char*argv[])
{
质量保证申请a(argc、argv);
qw;
QHBoxLayout*pH=新的QHBoxLayout(&w);
QPushButton*按钮=新的QPushButton(“运行线程”、&w);
MyLineEdit*lineEdit=新建MyLineEdit(&w);
pH->addWidget(按钮);
pH->addWidget(lineEdit);
w、 show();
神话阅读线程;
qDebug(“线程id%d”,(int)QThread::currentThreadId());
QObject::connect(按钮、信号(单击())、线程、插槽(开始());
QObject::connect(&thread)、signalGUI(const QString&)、lineEdit、SLOT(setText)(const
Thread id 1088110320
Thread id inside run 1093176208
String address inside run 0x41288350
Thread id inside setText 1088110320
String address inside setText 0x974af58
#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;
    thread.moveToThread(&thread);
    thread.start();
    qDebug("Thread id %d",(int)QThread::currentThreadId());
    QObject::connect(pushButton,SIGNAL(clicked()),&thread,SLOT(callRun()),Qt::QueuedConnection) ;
    QObject::connect(&thread,SIGNAL(signalGUI(QString)),lineEdit,SLOT(setText(QString)),Qt::DirectConnection);
    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()
 {
     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);

 }
 void MyThread::run()
 {
    exec();
 }