Почему сигнал QThread :: закончен, не излучается?

Я создал свой собственный TestService который работает на отдельном QThread, но когда MainLoop завершает QThread::finished сигнал не излучается. Я видел похожий вопрос, но проблема была немного другой, потому что ОП была перегрузка QThread тогда как я просто перемещаю свой класс в поток.

Обратите внимание, что Я не перегружаю QThread класс я только перегружаю QObject на основе этого примера: http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

Вот мой 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 не выбрасывается, как я могу это исправить?

2

Решение

Сигнал выполнено () получает излучение от причины, но вы его не улавливаете.

Вот:

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

Qt::QueuedConnection используется, как _thread а также this (сервис) находятся в разных темах.

Тем временем finished() испускается, _threadцикл обработки событий уже завершен, поэтому сигнал не будет доставлен в слот.

Вы можете явно использовать Qt::DirectConnection,

РЕДАКТИРОВАТЬ:

QTherad работает так:

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

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

Итак, к тому времени finished испускается, Eventloop уже остановить выполнение. И как вы двигаетесь service в _thread, цикл событий сервиса _thread цикл событий.

Обратите внимание, что QObject Сам по себе не имеет своего собственного цикла событий. Циклы событий создаются диалогами, потоками и приложениями.


На самом деле я буду рекомендовать в вашем простом случае просто использовать QtConcurent::run, поскольку вы не выполняете фактическую обработку событий в новом потоке, а просто запускаете одну функцию.

7

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector