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