サーチ…


備考

ここここの公式ドキュメントにはすでに述べられているいくつかのノートがあります

  • オブジェクトに親がある場合は、親と同じスレッドになければなりません。つまり、新しいスレッドに移動することはできません。また、親とオブジェクトが別のスレッドに存在する場合、親にオブジェクトを設定することもできません
  • オブジェクトが新しいスレッドに移動されると、そのすべての子も新しいスレッドに移動されます
  • 新しいスレッドにのみオブジェクトをプッシュできます。あなたはそれらを新しいスレッドに引き出すことはできません。つまり、オブジェクトが現在住んでいるスレッドからのみmoveToThreadを呼び出すことができます

QThreadの基本的な使い方

QThreadは、プラットフォームスレッドのハンドルです。スレッドの存続期間を監視し、スレッドが作業を終了するように要求することによってスレッドを管理できます。

ほとんどの場合、クラスを継承することはお勧めできません。デフォルトのrunメソッドは、イベントをクラスに属するオブジェクトにディスパッチできるイベントループを開始します。クロススレッド信号スロット接続は、 QMetaCallEventをターゲットオブジェクトにディスパッチすることによって実装されます。

QObjectインスタンスをスレッドに移動すると、スレッドイベントやスロット/メソッド呼び出しなどのイベントを処理します。

スレッドで作業を行うには、まずQObjectから派生した独自のワーカークラスを作成します。次にスレッドに移動します。オブジェクトはQMetaObject::invokeMethod()を使って自動的に独自のコードを実行できます。

#include <QObject>

class MyWorker : public QObject
{
    Q_OBJECT
public:
    Q_SLOT void doWork() {
        qDebug() << "doWork()" << QThread::currentThread();
        // and do some long operation here
    }
    MyWorker(QObject * parent = nullptr) : QObject{parent} {}
};

class MyController : public QObject
{
    Q_OBJECT
    Worker worker;
    QThread workerThread;
public:
    MyController()  {
        worker.moveToThread(&workerThread);
        // provide meaningful debug output
        workerThread.setObjectName("workerThread");
        workerThread.start();
        // the thread starts the event loop and blocks waiting for events
    }
    ~MyController()  {
        workerThread.quit();
        workerThread.wait();
    }
    void operate() {
        // Qt::QueuedConnection ensures that the slot is invoked in its own thread
        QMetaObject::invokeMethod(&worker, "doWork", Qt::QueuedConnection);
    }
};

ワーカーが一時的で、作業が完了している間だけ存在する必要がある場合は、 QtConcurrent::run介してスレッドプール内で実行するQtConcurrent::runまたはスレッドセーフメソッドを実行することをおQtConcurrent::run

Qt並行実行

QThreadsとmutexやセマフォーのような低レベルのプリミティブを管理することが複雑すぎると、Qt Concurrent名前空間があなたの探しているものです。これには、より高度なスレッド管理を可能にするクラスが含まれています。

Concurrent Runを見てみましょう。 QtConcurrent::run()は、新しいスレッドで関数を実行できるようにします。いつあなたはそれを使いたいですか?いくつかの長い操作があり、手動でスレッドを作成したくない場合。

今すぐコード:

#include <qtconcurrentrun.h>

void longOperationFunction(string parameter)
{
    // we are already in another thread
    // long stuff here
} 

void mainThreadFunction()
{
    QFuture<void> f = run(longOperationFunction, "argToPass");
    f.waitForFinished();
}

つまり、単純なことです:別のスレッドで別の関数を実行する必要があるときは、 QtConcurrent::run呼び出し、関数とそのパラメータを渡すだけです。

QFutureは、非同期計算の結果を示します。 QtConcurrent::run場合、関数の実行をキャンセルすることはできません。

他のスレッドからのスロットの呼び出し

Qtイベントループを使用して操作を実行し、非Qtユーザーがそのイベントループとやり取りする必要がある場合、別のスレッドからの通常の呼び出しを処理するためのスロットを作成すると、他のユーザーの作業が簡単になります。

main.cpp:

#include "OperationExecutioner.h"
#include <QCoreApplication>
#include <QThread>

int main(int argc, char** argv)
{
    QCoreApplication app(argc, argv);

    QThread thrd;
    thrd.setObjectName("thrd");
    thrd.start();
    while(!thrd.isRunning())
        QThread::msleep(10);

    OperationExecutioner* oe = new OperationExecutioner;
    oe->moveToThread(&thrd);
    oe->doIt1(123,'A');
    oe->deleteLater();
    thrd.quit();
    while(!thrd.isFinished())
        QThread::msleep(10);

    return 0;
}

OperationExecutioner.h:

#ifndef OPERATION_EXECUTIONER_H
#define OPERATION_EXECUTIONER_H

#include <QObject>

class OperationExecutioner : public QObject
{
    Q_OBJECT
public slots:
    void doIt1(int argi, char argc);
};

#endif  // OPERATION_EXECUTIONER_H

OperationExecutioner.cpp:

#include "OperationExecutioner.h"
#include <QMetaObject>
#include <QThread>
#include <QDebug>

void OperationExecutioner::doIt1(int argi, char argc)
{
    if (QThread::currentThread() != thread()) {
        qInfo() << "Called from thread" << QThread::currentThread();
        QMetaObject::invokeMethod(this, "doIt1", Qt::QueuedConnection,
                                  Q_ARG(int,argi), Q_ARG(char,argc));
        return;
    }

    qInfo() << "Called from thread" << QThread::currentThread()
            << "with args" << argi << argc;
}

OperationExecutioner.pro:

HEADERS += OperationExecutioner.h
SOURCES += main.cpp OperationExecutioner.cpp
QT -= gui


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow