Pregunta

¿Qué significa para mover un objeto de un hilo a otro en el uso de Qt moveToThread?Todo parece funcionar incluso antes de usar moveToThread, el cual se mueve el objeto a partir de un hilo (GUI hilo) a un otro hilo ( trabajado) y Qt:conectar las llamadas a la ranura correspondiente en el objeto.

Hay alguna diferencia debido a que el objeto vidas, interfaz gráfica de usuario de la rosca o el subproceso de trabajo?

EDITAR:He hecho un pequeño programa, pero no entiendo cómo QThread trabaja junto con la Señal y de la ranura de la función, le agradecería si pudiera explicar lo que es el uso de moveToThread con el ejemplo

#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);
 }
¿Fue útil?

Solución

Tome un vistazo a Señales y las ranuras a través de hilos . Si siempre utiliza señales y ranuras para comunicarse con el subproceso de trabajo, Qt se encarga de la moveToThread para usted si se necesita y que utiliza la conexión correcta.

Edit: Yo diría que el autor del artículo fue ver a su problema, ya que estaba llamando inicio en el constructor antes de que el hilo se crea realmente. En otras palabras, no confían en el código de terceros a ciegas.

Editar: En respuesta a su comentario, mira el Mandelbrot ejemplo, bajo el encabezado MandelbrotWidget Class Implementation:

  

Con conexiones en cola, Qt debe guardar una copia de los argumentos que se han pasado a la señal para que pueda pasar a la ranura más adelante. Qt sabe cómo tomar de copia de muchos tipos de C ++ y Qt, pero QImage no es uno de ellos. Por tanto, debemos llamar a la función de plantilla qRegisterMetaType () antes de que podamos utilizar como parámetro en QImage conexiones en cola.

Creo que esto es un poco anticuado, aquí son los meta tipos válidos . Dado que las señales y ranuras a través de las discusiones utilizan conexiones en cola, que no debería tener que hacer el moveToThread llama en la mayoría de los casos.

Editar: Voy a tratar de explicar las cosas con un ejemplo similar:

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:

#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

#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

#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();
}

Ejemplo de salida después de botón de clic:

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

Como se puede ver, el hilo de ejecución es diferente que el hilo principal interfaz gráfica de usuario. Además, aunque se pasa una referencia constante a un QString, ya que atraviesa las fronteras de rosca lo copia. I fuertemente Le recomendamos que lea Hilos y QObject .

Otros consejos

  1. El método QThread::start() crea el hilo y llama a su aplicación run(). Si desea gestionar eventos o señales recibidas en la rosca tiene que llamar QThread::exec() dentro de su aplicación run(). Nunca se debe llamar run() explícita y nunca se debe llamar exec() fuera del run().

  2. El hilo dueño hace una diferencia sólo cuando una ranura está conectada a una señal con el tipo de conexión que no sea Qt::DirectConnection. Entonces Qt se asegurará de que la ranura se ejecuta en el hilo propietario, pero para que el hilo propietario debe ejecutar un bucle de eventos con QThread::exec(). En este caso llamando myObj.moveToThread(myThread) se asegurará de que myObj ranuras se ejecutan en el myThread hilo.

  3. El objeto hilo pertenece a la rosca en la que se ha creado, no en el hilo que se las arregla (y donde el método de ejecución se ejecutará). Así que cuando se conecta una señal a la ranura de un objeto hilo, ese espacio se ejecutará en el hilo de rosca donde el objeto fue creado a menos que llame moveToThread().

Al mover un objeto entre los hilos, usted decide que bucle de eventos a la que pertenece.Al hacer las conexiones en el interior de un hilo, el código de señalización llama directamente a cada una de las ranuras (tener que esperar a que terminen).La señalización a través del hilo de los límites de los lugares de la señal de llamada en el bucle de eventos, dejar que la ranura del hilo de realizar la llamada a la ranura cuando esté listo.

Hacer llamadas directas entre hilos requiere de usted para asegurarse de que sus funciones son de reentrada.También debe asegurarse de proteger sus datos con los mutexes o semáforos y al mismo tiempo evitar las condiciones de carrera.

En el artículo, supongo que el retraso es debido a la llamada directa, es decir,no en todos los procesados en el fondo (pero yo sólo desnatada en el texto).

#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();
 }

Nuevo objeto hilo es creado y el objeto hilo se mueve a la misma rosca. Las señales son ahora a través de hilos y tipo de conexión son a la vez la cola y funciona como se esperaba.

algunos objetos sólo pueden ser utilizados en la rosca propietario. por ejemplo, si se crea y objeto de socket en un hilo y que desea enviar y datos recv en otro hilo que is'nt posible. por lo tanto, una solución es mover el objeto a partir de un hilo a otro y operar en él.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top