2010-07-09 16 views
8

Ho una semplice interfaccia utente modulo che ha uno slot per un pulsante, iniziando un filo:QThread blocco principale

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

E il metodo run() si presenta come segue:

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

Quando Faccio clic sul pulsante che chiama LoadImage(), l'interfaccia utente non risponde. Periodicamente vedo il messaggio "ping" come l'output di debug ma l'interfaccia si blocca, non risponde a nulla. Perché il mio thread non funziona separatamente? CameraThread derivata come pubblico QThread Sto usando gcc versione 4.4.3 (Ubuntu 4.4.3-4ubuntu5) con librerie QT e QT Creator da repository Ubuntu 10.04 (x86).

risposta

27

Risposta breve: Avviare il filo chiamando aThread->start(); non run(), e assicurarsi che si filo di metodo run() è protetto (non pubblica).

Spiegazione

Calling start() is the correct way per avviare il filo, in quanto fornisce scheduling priorità ed effettivamente esegue il metodo run() nel proprio contesto thread.

Sembra che si sta per essere il caricamento di immagini in questa discussione, così ho intenzione di includere alcuni consigli prima di incorrere in trappole molte persone cadono in durante l'utilizzo QThread

  1. QThread sé non è un filo. E 'solo un wrapper per un filo, questo ci porta alla ..
  2. segnali/slot definiti nella classe CameraThread non necessariamente eseguito in un contesto del thread, ricordo solo il metodo run() e metodi di chiamata da esso sono in esecuzione in un thread separato.

IMHO, sottoclasse QThread nel maggior parte dei casi ènon la strada da percorrere. Puoi farlo molto più semplice con il seguente codice, e ti farà risparmiare molti mal di testa.

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

Leggere anche il numero Qt blog relativo a questo argomento.

+0

La documentazione QT spiega l'utilizzo di QThread tramite sottoclasse. Perché è una cattiva idea? –

+1

@Atilla - se leggi il link del blog QT nella risposta di Casey, troverai il titolo "Stai sbagliando ...". È una discussione sul perché la documentazione di Qt sulla sottoclasse di QThread non era il modo corretto di fare discussioni.Inoltre, se ho letto correttamente il post di blog, è dalla persona che ha scritto la documentazione Qt originale. –

+2

Sì, è corretto. Fondamentalmente, la documentazione Qt è fuorviante e di conseguenza ha portato molte persone a fare cose hacky (come movetoThread (questo) nel costruttore Qthread) che causano problemi su tutta la linea. Speriamo che i documenti vengano aggiornati a breve. – Casey

4

Devi chiamare thread-> start() non eseguito ... run è un punto di ingresso per thread. Il thread è iniziato con start. Chiami direttamente, è per questo che blocchi la tua GUI. Controlla la documentazione di QThread. virtuale vuoto QThread :: run() è protetto (non senza un motivo)

-1

Penso che il problema potrebbe essere che non si chiama QtCore.QThread._init __ (self) nel costruttore. Ho avuto lo stesso problema. Inoltre, penso che non dovresti ignorare la funzione di avvio, basta sovrascrivere la funzione run(). Questo ha risolto lo stesso problema che stavo avendo. Anche senza ritardi di sleep(), la finestra dovrebbe essere reattiva.

+1

No, il mio problema era chiamare run() di start(). Ho già eseguito l'override di run(). –

Problemi correlati