2

TestService別の で実行される独自のものを作成しましたQThreadが、 がMainLoop終了してもQThread::finished信号は発信されません。同様の質問を見ましたがQThread、クラスをスレッドに移動するだけでOPがオーバーロードしていたため、問題は少し異なりました。

クラスをオーバーロードしていないことに注意してください。次の例に基づいてのみオーバーロードします。 /QThreadQObject

これが私のTestServiceクラスです:

#include <QObject>
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <iostream>

using namespace std;
class TestService: public QObject
{
    Q_OBJECT;
private:
    volatile int _count;
    QWaitCondition _monitor;
    QMutex _mutex;
    QThread* _thread;

public:
    TestService(int numSeconds)
    {
        _count = numSeconds;
        _thread = NULL;
        cout << "TestService()" << endl;
    }

    virtual ~TestService()
    {
        cout << "~TestService()" << endl;
    }

    void Start()
    {
        QMutexLocker locker(&_mutex);
        if(_thread == NULL)
        {
            _thread = new QThread;

            // Move this service to a new thread
            this->moveToThread(_thread);

            // The main loop will be executed when the thread
            // signals that it has started.
            connect(_thread, SIGNAL(started()), this, SLOT(MainLoop()));

            // Make sure that we notify ourselves when the thread
            // is finished in order to correctly clean-up the thread.
            connect(_thread, SIGNAL(finished()), this, SLOT(OnFinished()));

            // The thread will quit when the sercives
            // signals that it's finished.
            connect(this, SIGNAL(Finished()), _thread, SLOT(quit()));

            // The thread will be scheduled for deletion when the 
            // service signals that it's finished
            connect(this, SIGNAL(Finished()), _thread, SLOT(deleteLater()));

            // Start the thread
            _thread->start();
        }
    }

    void Stop()
    {
        _count = 0;
        _monitor.wakeAll();
    }
private slots:
    void MainLoop()
    {
        cout << "MainLoop() Entered" << endl;
        while(_count > 0)
        {
            cout << "T minus " << _count << " seconds." << endl;

            QMutexLocker locker(&_mutex);
            _monitor.wait(&_mutex, 1000);
            _count--;
        }
        cout << "MainLoop() Finished" << endl;
        emit Finished();
    }

    virtual void OnFinished()
    {
        cout << "OnFinished()" << endl;
    }
signals:
    void Finished();
};

テストコードは次のとおりです。

void ServiceTest()
{
    cout << "Press q to quit." << endl;
    cout << "Press s to start." << endl;
    cout << "Press t to stop." << endl;
    QSharedPointer<TestService> testService(new TestService(10));
    char in = 'a';
    while( in != 'q' )
    {
        switch(tolower(in))
        {
        case 's':
            testService->Start();
            break;
        case 't':
            testService->Stop();
            break;
        default:
            break;
        }
        cin.get(in);
        in = tolower(in);
    }
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    ServiceTest();

    QTimer::singleShot(0, &a, SLOT(quit()));

    return a.exec();
}

出力は次のとおりです。

Press q to quit.
Press s to start.
Press t to stop.
TestService()
s
MainLoop() Entered
T minus 10 seconds.
T minus 9 seconds.
T minus 8 seconds.
t
MainLoop() Finished
q
~TestService()
Press any key to continue . . .

なぜfinished私がそれを修正できるのか、誰でも説明できますか?

4

1 に答える 1

8

シグナル finished() は原因で発行されますが、キャッチしません。

ここ:

connect(_thread, SIGNAL(finished()), this, SLOT(OnFinished()));

Qt::QueuedConnection_threadthis(サービス) が異なるスレッドにあるため、 が使用されます。

finished()が発行されるまでに、_threadのイベント ループは既に実行を終了しているため、シグナルはスロットに配信されません。

を明示的に使用できますQt::DirectConnection

編集:

QTherad は次のように機能します。

QThread::start()
{
    emit started();
    run();
    emit finished();
}

QThread::run()
{
     eventloop->exec();
}

したがって、finishedイベントループが発行されるまでに、イベントループはすでに実行を停止しています。そして、 に移るservice_thread、サービスのイベント ループは_threadイベント ループです。

QObjectそれ自体には独自のイベントループがないことに注意してください。イベント ループは、ダイアログ、スレッド、およびアプリケーションによって作成されます。


QtConcurent::run実際には、新しいスレッドで実際のイベント処理を実行せず、単一の関数を実行するだけなので、単純なケースでは を使用することをお勧めします。

于 2012-11-19T18:56:42.023 に答える