4

さまざまな時点で子スレッド関数を呼び出すメイン スレッドがありますが、それが Qt で正しい方法であるかどうかはわかりません。以下のコードの何が問題であり、より良い代替手段を探しています。

メインスレッドがロック子を解放するたびに、メインスレッドが無限に実行されます。

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

3 に答える 3

4

編集:基本もカバーするために投稿全体を作り直します。

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

サンプル出力:

主な機能はスレッドで実行されました:1087038064
子関数がスレッドで実行されました:1091267472
子関数がスレッドで実行されました:1093417872
同時子関数がスレッドで実行されました:1095519120
同時子関数がスレッドで実行されました:1097644944

ヘッダーファイルでmocを実行していることを確認してください。qmakecmakeはどちらもmakefileの作成をサポートしています。

コードのビルドに使用したCMakeLists.txtファイルは次のとおりです。

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)
于 2009-09-13T14:05:33.507 に答える
3

実際、問題に対する現在の解決策は非常に優れたハックです。

「よりクリーンな」方法で実行したい場合は、ワーカー スレッドでイベント ループを開始する必要があります。その後、ワーカー スレッドはメイン スレッドからシグナルを受信できるようになります。操作をトリガーするために、メイン スレッドから (シグナル/スロット メカニズムを使用して) 子スレッドで関数を呼び出すことができます。

詳細については、http: //doc.trolltech.com/4.2/threads.html#per-thread-event-loopを参照してください。

(ヒント: 重要なアイデアは、ワーカー スレッドで受信オブジェクトを作成することです。その後、そのスロットはそのスレッドで処理されます。または、MoveToThread() 関数を使用することもできます)。

于 2009-09-11T09:37:45.727 に答える
0

通常の Qt スタイルに合わせて、そのためにシグナルを使用することをお勧めします。この質問をチェックしてください。そこで受け入れられた答えもあなたの質問と一致しているようです。

于 2009-09-11T09:36:57.603 に答える