Сигнал QThread finished () никогда не испускается

Итак, у меня есть рабочий класс с двумя ячейками: StartWork () и StopWork (), StartWork () запускает бесконечный цикл (он просто читает и считывает данные с камеры без остановки), а метод StopWork () просто устанавливает логическое значение значение false (поэтому цикл внутри StartWork () останавливается).

согласно документации QThread, лучший способ использовать их сейчас - не разделять их на подклассы, а перемещать рабочих в поток, вот что я делаю. проблема в том, что сигнал start () из потока вызывается, но сигнал finished () никогда не вызывается.

Слоты рабочего класса:

void StartWork () {работает = правда; в то время как (работает) {делать работу; }}

void StopWork () {работает = ложь; }

Инициализация 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 (), и все прекрасно (графический интерфейс работает без блоков и т. д.).

но thread-> quit () ничего не делает, он вызывается (потому что кнопка меняет текст), но это все. если я просто вызываю worker-> StopWork (), он работает, но потом я не могу запустить его снова.

Я пробовал с thread-> exit (); но результаты те же. Также я знаю, что подклассы работают, но это выглядит уродливее, и, согласно недавней документации Qt, подклассы больше не оптимальны.

заранее спасибо.


person sap    schedule 17.10.2012    source источник


Ответы (1)


У вас есть бесконечный цикл:

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() заставит эту функцию завершиться, поэтому в цикле событий не будет событий для обработки, и поток будет завершен).

person Synxis    schedule 17.10.2012
comment
Вы, наверное, забыли удалить while(running) в doWork. - person Lol4t0; 18.10.2012
comment
привет и большое спасибо за ответ. Мне потребовалось время, чтобы ответить, потому что я читал документацию по таймеру. Мне сложно понять, где разместить таймер. Я попытался разместить его внутри рабочего класса, но Qt дал мне 2 ошибки: не могу запустить таймеры из другого потока и не могу остановить таймеры из другого потока, поэтому я предполагаю, что таймер должен находиться за пределами рабочего класса? попробовал это, используя if (running) вместо while, так как StartWork () и StopWork () теперь просто переключают текущее логическое значение, но это не сработало. не могли бы вы лучше объяснить, где разместить QTimer, пожалуйста? Благодарю. - person sap; 18.10.2012
comment
@Lol Исправлено, спасибо. Для sap: вы должны запустить таймер после перемещения рабочего в поток - person Synxis; 18.10.2012
comment
Привет, Synxis, всем. Извините за новичок, но зачем ставить таймер? и где? Спасибо - person DannyK; 18.10.2012
comment
@smurff Таймер предназначен для имитации непрерывной работы, вызывая ее основную часть через равные промежутки времени. Не забудьте увидеть мою правку. - person Synxis; 18.10.2012