3

StartWork() と StopWork() の 2 つのスロットを持つワーカー クラスがあります。変数を false に設定します (したがって、StartWork() 内のループが停止します)。

QThread のドキュメントによると、現在それらを使用する最善の方法は、サブクラス化ではなく、ワーカーをスレッドに移動することです。問題は、スレッドからの started() シグナルが呼び出されますが、 finished() シグナルが呼び出されないことです。

ワーカー クラス スロット:

void StartWork(){ 実行中 = true; while(running){ 仕事をする; }}

void StopWork(){ 実行中 = false; }

QThread の初期化とシグナル/スロット接続:

thread = new QThread();
worker = new Worker();
worker.moveToThread(thread);

QObject::connect(thread, SIGNAL(started()), worker, SLOT(StartWork()));
QObject::connect(thread, SIGNAL(finished()), worker, SLOT(StopWork()));

そして私のQPushButtonで私はこれを行います:

if(pushStartStop->text().toLower() == "start")
{
    pushStartStop->setText("Stop");
    thread->start();
}
else
{
    pushStartStop->setText("Start");
    thread->quit();
}

thread->start() は正常に動作し、StartWork() が呼び出され、すべてが美しい (GUI はブロックなしで実行されるなど)。

しかし、thread->quit() は何もしません。(ボタンがテキストを変更するため) 呼び出されますが、それだけです。worker->StopWork() を呼び出すだけで機能しますが、再度開始することはできません。

私は thread->exit(); で試しました。しかし、結果は同じです。また、サブクラス化が機能することは知っていますが、見栄えが悪く、最近の Qt ドキュメントによると、サブクラス化は最適ではなくなりました。

前もって感謝します。

4

1 に答える 1

5

あなたは永久ループを持っています:

void StartWork()
{
    running = true;
    while(running)
    {
        do work;
    }
}

この関数はループするため、 を発行した直後にスレッドのイベント ループがブロックされstarted()ます。したがって、finished()放出することはできません。

解決策 1:

関数を追加する

void DoWork()
{
    if(running)
    {
        do work
    }
}

ワーカーへ、および変更

void StartWork()
{
    running = true;
}

次に、DoWorkスレッド内のタイマーに接続するだけです。

解決策 2:

機能を変更する

void StartWork()
{
    running = true;
    while(running)
    {
        do work;
        QCoreApplication::processEvents();
    }
}

このソリューションでは、ワーカーがジョブを停止したときにスレッドを再起動する必要があります (StopWork()この関数は強制的に終了されるため、イベント ループには処理するイベントがなく、スレッドは終了します)。

于 2012-10-17T20:07:55.377 に答える