Domanda

Ho un thread principale che invoca una funzione thread figlio in momenti diversi, ma non sono sicuro che sia il modo giusto di farlo in Qt. Cosa c'è di sbagliato nel codice qui sotto e cercare un'alternativa migliore

Esiste un thread principale in esecuzione all'infinito quando ogni thread principale rilascia il blocco figlio fa un lavoro.

#include <QtCore/QCoreApplication>
#include <QSemaphore>
#include <QThread> 
QSemaphore sem(0);
class Background : public QThread 
{
protected:
void run() 
{ 
for(;;)
{ 
   sem.acquire(1); 
   qDebug("Child function ran");
} 
} 
};

int main(int argc, char *argv[])  
{   
QCoreApplication a(argc, argv);   
Background child; 
child.start();
qDebug("Main running"); 
qDebug("release a lock");
sem.release(1);
qDebug("Do somework in main");   
//call child
sem.release(1);
sem.release(1);
return a.exec();  
}
È stato utile?

Soluzione

Modifica: rielabora l'intero post per coprire anche le basi.

Background.h :

#ifndef BACKGROUND_H
#define BACKGROUND_H

#include <QThread>
#include <QObject>

class Background : public QThread 
{
Q_OBJECT
public:
   Background(QObject* parent = 0):QThread(parent){}
protected:
   void run()
   {
      qDebug(qPrintable(QString("Child function ran in thread: %1").arg(QThread::currentThreadId())));
   }
};

class BackgroundConcurrent : public QObject
{
Q_OBJECT
public:
   BackgroundConcurrent(QObject* parent = 0):QObject(parent){}
public slots:
   void doWork() const
   {
      qDebug(qPrintable(QString("Concurrent child function ran in thread: %1").arg(QThread::currentThreadId())));
   }
};

class BackgroundTrigger : public QObject
{
Q_OBJECT
public:
   BackgroundTrigger(QObject* parent = 0):QObject(parent){}
   ~BackgroundTrigger()
   {
      foreach(QObject* child, children())
      {
         QThread* childThread = qobject_cast<QThread*>(child);
         if (childThread)
            childThread->wait();
      }
   }
public slots:
   void triggerWorker()
   {
      Background* child = new Background(this);
      child->start();
   }
};

#endif // BACKGROUND_H

main.cpp :

#include "Background.h"

#include <QCoreApplication>
#include <QtConcurrentRun>

int main(int argc, char *argv[])  
{   
QCoreApplication a(argc, argv);   

// Using QThread
BackgroundTrigger childTrigger;
qDebug(qPrintable(QString("Main function ran in thread: %1").arg(QThread::currentThreadId())));

// Call child
childTrigger.triggerWorker();
childTrigger.triggerWorker();

// Using QtConcurrent
BackgroundConcurrent cchild;
QFuture<void> future1 = QtConcurrent::run(&cchild, &BackgroundConcurrent::doWork);
QFuture<void> future2 = QtConcurrent::run(&cchild, &BackgroundConcurrent::doWork);

return 0;
}

Output di esempio:

Main function ran in thread: 1087038064
Child function ran in thread: 1091267472
Child function ran in thread: 1093417872
Concurrent child function ran in thread: 1095519120
Concurrent child function ran in thread: 1097644944

Assicurati di eseguire moc sui file di intestazione, qmake e < a href = "http://www.cmake.org/cmake/help/documentation.html" rel = "nofollow noreferrer"> cmake entrambi supportano la creazione dei tuoi makefile.

Ecco il file CMakeLists.txt che ho usato per costruire il codice:

cmake_minimum_required(VERSION 2.6)

#Project name
project(TEST)

#Use Qt4
find_package(Qt4)

if(QT4_FOUND)
set(QT_USE_QTOPENGL TRUE)
include(${QT_USE_FILE})

set(LIBS
    ${QT_LIBRARIES}
    )

#Source files (*.cpp, *.o)
set(TEST_SRCS main.cpp)

#Header files (*.h[pp])
set(TEST_HDRS Background.h)

#Qt macros to handle uic, moc, etc...
QT4_WRAP_CPP(TEST_MOC ${TEST_HDRS} OPTIONS -nw)

set(TEST_ALLSRC ${TEST_SRCS} ${TEST_MOC})

#Create main
add_executable(test ${TEST_ALLSRC})
target_link_libraries(test ${LIBS})

endif(QT4_FOUND)

Altri suggerimenti

In realtà la tua attuale soluzione al problema è un bel trucco.

Se preferisci farlo in un " più pulito " moda, dovresti iniziare un ciclo di eventi nel tuo thread di lavoro. Quindi il thread di lavoro sarà in grado di ricevere segnali dal thread principale. È possibile chiamare una funzione nel thread figlio (utilizzando il meccanismo segnale / slot) dal thread principale per attivare l'operazione.

Vedi qui per maggiori dettagli: http://doc.trolltech.com/4.2/threads. html # per-thread-evento-loop

(Suggerimento: l'idea chiave è che si crea l'oggetto di ricezione nel thread di lavoro; quindi i suoi slot verranno elaborati in quel thread; oppure è possibile utilizzare la funzione MoveToThread ())

Sembra che potresti voler usare un segnale per farlo, per adattarlo al normale stile Qt. Dai un'occhiata a questa domanda ; la risposta accettata sembra corrispondere anche alla tua domanda.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top