2010-07-09 18 views
8

Tengo una sencilla interfaz de usuario de forma que tiene una ranura para un botón, a partir de un hilo:QThread bloqueo principal aplicación

void MainWindow::LoadImage() 
{ 
    aThread->run(); 
} 

Y el método run() es el siguiente:

void CameraThread::run() 
{ 
    qDebug("Staring Thread"); 
    while(1) 
    { 
     qDebug("ping"); 
     QThread::sleep(1); 
    } 
} 

Cuando Hago clic en el botón que llama a LoadImage(), la IU deja de responder. Periódicamente veo el mensaje "ping" como salida de depuración pero la UI se cuelga, no responde a nada. ¿Por qué mi hilo no se ejecuta por separado? CameraThread derivado como QThread público Estoy usando gcc versión 4.4.3 (Ubuntu 4.4.3-4ubuntu5) con las bibliotecas QT y QT Creator desde los repositorios de Ubuntu 10.04 (x86).

Respuesta

27

Respuesta corta: Comience el hilo llamando aThread->start(); no run(), y asegúrese de que el hilo de método run() está protegido (no público).

Explicación

Calling start() is the correct way para iniciar el hilo, ya que proporciona programación de prioridad y en realidad ejecuta el método run() en su propio contexto hilo.

Parece que se van a cargar imágenes en este hilo, así que voy a incluir algunos consejos antes de ejecutar en trampas muchas personas caen en durante el uso de QThread

  1. QThread sí no es un hilo. Es simplemente una envoltura alrededor de un hilo, esto nos lleva a ..
  2. señales/slots definidos en la clase CameraThread no necesariamente ejecutar en el contexto de la rosca, recuerde sólo el método y los métodos run() llamada de ella se ejecutan en un hilo separado.

en mi humilde opinión, la subclasificación QThread en el mayoría de los casos es no el camino a seguir. Puede hacerlo mucho más simple con el siguiente código, y le ahorrará muchos dolores de cabeza.

class ImageLoader : public QObject { 
Q_OBJECT 
public slots: 
    void doWork() 
    { 
     // do work 
    } 
}; 

void MainWindow::MainWindow(/*params*/) 
{ 
    ImageLoader loader; 
    QThread thread; 
    loader.moveToThread(&thread); 
    connect(this, SIGNAL(loadImage()), &loader ,SLOT(doWork())); 
    thread.start(); 
    // other initialization 
} 
void MainWindow::LoadImage() 
{ 
    emit loadImage(); 
} 

Lea también el Qt blog sobre este tema.

+0

La documentación de QT explica el uso de QThread por subclases. ¿Por qué es eso una mala idea? –

+1

@Atilla: si lees el enlace QT Blog en la respuesta de Casey, lo encontrarás titulado "Lo estás haciendo mal ...". Es una discusión sobre por qué la documentación de Qt sobre la subclasificación de QThread no era la forma correcta de hacer subprocesos.Además, si he leído la entrada del blog correctamente, es por la persona que escribió la documentación original de Qt. –

+2

Sí, eso es correcto. Básicamente, la documentación de Qt es engañosa y, en consecuencia, ha llevado a muchas personas a hacer cosas hacky (como movetoThread (esto) en el constructor de Qthread) que causan problemas en el futuro. Esperemos que los documentos se actualizarán pronto. – Casey

4

Tienes que llamar a thread-> start() no ejecutar ... run es un punto de entrada para el hilo. El hilo se inicia con el inicio. Llamas directamente a correr, es por eso que bloqueas tu GUI. Verifique la documentación de QThread. virtual de vacío QThread :: run() está protegido (no sin razón)

-1

Creo que el problema podría ser que no está llamando a QtCore.QThread._init __ (self) en el constructor. Tuve el mismo problema. Además, creo que no debe anular la función de inicio, simplemente anular la función run(). Esto resolvió el mismo problema que estaba teniendo. Incluso sin retrasos en el modo inactivo(), la ventana debe responder.

+1

No, mi problema fue llamar a run() en su lugar de inicio(). Ya sobreescribo run(). –

Cuestiones relacionadas