1

クリーンアップ作業を容易にするために、ワーカー オブジェクトの親を移動先の Qthread に設定したいと考えています。(下記参照)。

void TelnetServer::incomingConnection(qintptr socketDescriptor)
{
    QThread * TelnetConnectionThread = new QThread(this);
    TelnetConnection *worker = new TelnetConnection(socketDescriptor,TelnetConnectionThread);
    connect(TelnetConnectionThread, SIGNAL(started()), worker, SLOT(start()));
    connect(TelnetConnectionThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
    worker->moveToThread(TelnetConnectionThread);  // Move worker into QThread
    TelnetConnectionThread->start();  
}

start() 行の直前に、次のように追加しました。

worker->setParent(TelnetConnectionThread);

しかし、実行時に、新しい親が別のスレッドにあるため、それを行うことができないというエラーが表示されます。それはどうしてですか?上記の行では、ワーカーを新しいスレッドに移動しました...そのため、ワーカーは TelnetConnectionThread と同じスレッドにある必要があります。ヘルプ?


ワーカーが実際に新しいスレッドに移動することを、いくつかの qDebug と thread() で確認しました!

4

1 に答える 1

5

QThread について少し混乱していると思います。最初の問題は、実際にはスレッドではなくスレッド コントローラーであるため、その名前がかなり誤解を招くことです。次は、スレッド アフィニティ (オブジェクトが実際に実行されているスレッド) の問題です。

メイン スレッドで開始して新しい QThread を作成すると、スレッド コントローラーはメインスレッドでインスタンス化されます。

QThread* pThread = new QThread;

次にスレッドが開始されます: -

pThread->start();

pThread は別のスレッドで実行されていると考えられますが、そのスレッド アフィニティは依然としてメインスレッドですが、pThread に移動される QObject ベースのクラス インスタンスには、新しいスレッドのスレッド アフィニティがあります。

QObject* pObject = new QObject;
pObject->moveToThread(pThread);

それでも、pThread のスレッド アフィニティはメインスレッドであり、pObject のスレッド アフィニティは新しいスレッドです。覚えておいてください、pThread は実際にはスレッド コントローラです!

スレッド アフィニティが異なるため、pObject の親を pThread に設定するのは正しくありません。これは、QThread を別のエンティティとして使用して QObject を移動するのではなく、QThread から継承しようとするときに多くの人が遭遇する問題です。通常発生するのは、継承された QThread クラスのコンストラクターでオブジェクトが作成され、それらを親にせず、それらのオブジェクトが期待どおりの新しいスレッドではなく、メイン スレッドのスレッド アフィニティを持つことに気付かないことです。

QObject を別のスレッドに移動すると、その子も移動するため、親をスレッド (スレッド コントローラー!) として設定しようとしても意味がありません。

要約すると、異なるスレッドで実行されるため、ワーカー オブジェクトの親を TelnetConnectionThread に設定することはできません。

ただし、終了後にスレッドのクリーンアップを実行しようとしている場合は、次のようにすることができます。

connect(TelnetConnectionThread, SIGNAL(finished()), TelnetConnectionThread, SLOT(deleteLater()));
于 2013-10-10T15:51:45.760 に答える