スレッドの作成
カスタムスレッドクラス
#ifndef CUSTOMETHREAD_H
#define CUSTOMETHREAD_H
#include <QObject>
#include <QThread>
#include "add.h"
class CustomeThread : public QThread
{
Q_OBJECT
public:
// Bind the thread kernel function.
explicit CustomeThread(Add*& addPtr);
private:
// Run the thread kernel function
virtual void run() override;
private:
Add* m_addFuc {
nullptr};
};
#endif // CUSTOMETHREAD_H
メイン機能
#include <QCoreApplication>
#include <QDebug>
#include <QThread>
#include "add.h"
#include "customethread.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << "Current thread id: " << QThread::currentThreadId();
//Concrator the thread kernel function object.
Add* ladd = new Add();
CustomeThread* thread = new CustomeThread(ladd);
thread->start();
return a.exec();
}
結果:
Current thread id: 0x36d0
current Thread: 0x7f50
100 + 200 = 300
計算のコア機能は子スレッドで実行されます。
スレッドコントローラクラスを作成することで、スレッドが実行するカーネル関数をバインドします。次に、子スレッドの run 関数でカーネル関数を実行します。
改善する
上記のプログラムでは、カーネル関数と実行スレッドが同じスレッド内にないため、Qt はクロススレッド呼び出し機構を通じてサブスレッドで正常に呼び出しましたが、結局のところ、これは安全ではないメソッドです。安全のため、カーネル関数を子スレッドに移動する必要があります。
#include <QCoreApplication>
#include <QDebug>
#include <QThread>
#include "add.h"
#include "customethread.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << "Current thread id: " << QThread::currentThreadId();
//Concrator the thread kernel function object.
Add* ladd = new Add();
CustomeThread* thread = new CustomeThread(ladd);
ladd->moveToThread(thread);
thread->start();
return a.exec();
}
糸ループ
イベントループ
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
return a.exec();
}
上記の a.exec() により、プログラムはシステムのイベント ループに入ることができます。イベント ループは特別な無限ループであり、その機能は次のとおりです。
- スレッドが実行を継続できるようにプログラムをブロックします。
- ループ内では、システムから送信される信号を継続的に監視し、応答することができます。
#include <QCoreApplication>
#include <QDebug>
#include <QThread>
#include <QTimer>
#include <QObject>
#include "add.h"
#include "customethread.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << "Current thread id: " << QThread::currentThreadId();
Add* ladd = new Add();
CustomeThread* thread = new CustomeThread(ladd);
ladd->moveToThread(thread);
thread->start();
QTimer* timer = new QTimer();
QObject::connect(timer, SIGNAL(timeout()), ladd, SLOT(add()));
return a.exec();
}
この例では、タイマーを使用して子スレッドのカーネル オブジェクトにシグナルを送信し、add() スロット関数を開始します。しかし、結局それは発動しなかった。理由の 1 つは、現時点では、ladd はすでに子スレッド内にあり、シグナル スロットに直接接続されているため、ほとんどの場合、シグナル関数とスロット関数が同じスレッド内にある場合にのみ有効になるためです。たとえば、ladd を子スレッドに移動しません。
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << "Current thread id: " << QThread::currentThreadId();
Add* ladd = new Add();
CustomeThread* thread = new CustomeThread(ladd);
// Not move ladd to subthread!!!!
//ladd->moveToThread(thread);
thread->start();
QTimer* timer = new QTimer();
QObject::connect(timer, SIGNAL(timeout()), ladd, SLOT(add()));
return a.exec();
}
Main thread id: 0x5628
Current Thread: 0x5628
100 + 100 = 200
Current Thread: 0x5628
100 + 100 = 200
Current Thread: 0x5628
100 + 100 = 200
Current Thread: 0x5628
100 + 100 = 200
Current Thread: 0x5628
100 + 100 = 200
子スレッドオブジェクトに信号を送信するにはどうすればよいですか?
このように信号と操作を接続できます
QObject::connect(timer, SIGNAL(timeout()), ladd, SLOT(add()), Qt::QueuedConnection);
シグナルが子スレッドに送信された場合、子スレッドはそれを受け入れることができますか?
しかし、この方法でも子スレッドにシグナルを送信できないことがわかりました。これは、子スレッドの run 関数がイベント ループを呼び出していないためです。この時点では、子スレッドは終了して終了しているため、子スレッドの run 関数にイベント ループを追加できます。
void CustomeThread::run()
{
exec();
}
Main thread id: 0x5384
Current Thread: 0x1638
100 + 100 = 200
Current Thread: 0x1638