Qtの子スレッドで関数を呼び出しますか?
質問
異なる時間に子スレッド関数を呼び出すメインスレッドがありますが、それが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();
}
解決
編集:基本もカバーするように投稿全体を作り直します。
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;
}
サンプル出力:
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
ヘッダーファイル、 qmake および< href = "http://www.cmake.org/cmake/help/documentation.html" rel = "nofollow noreferrer"> cmake はどちらもメイクファイルの作成をサポートしています。
コードの作成に使用した 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)
他のヒント
実際にあなたの問題に対するあなたの現在の解決策は非常に素晴らしいハックです。
「クリーナー」で行う場合ファッションでは、ワーカースレッドでイベントループを開始する必要があります。その後、ワーカースレッドはメインスレッドから信号を受信できるようになります。メインスレッドから(シグナル/スロットメカニズムを使用して)子スレッドの関数を呼び出して、操作をトリガーできます。
詳細については、こちらをご覧ください。 http://doc.trolltech.com/4.2/threads。 html#per-thread-event-loop
(ヒント:重要なアイデアは、ワーカースレッドで受信オブジェクトを作成することです;その後、そのスレッドでそのスロットが処理されます;またはMoveToThread()関数を使用できます)
通常のQtスタイルに合うように、そのためのシグナルを使用する必要があるようです。 この質問をご覧ください。受け入れられた回答もあなたの質問と一致するようです。