Я пытаюсь сказать нить, чтобы выйти изящно. Для этой цели поток проверяет на каждой итерации глобальный логический флаг, который указывает, должен ли поток продолжить или выйти. Нить настройки, как это (код из http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/):Почему мои потоки не выходят изящно?
ImageFusionQt::ImageFusionQt(QWidget* parent)
: QMainWindow(parent)
{
captureThread = new QThread();
captureWorker = new CaptureWorker();
// Connects the threads started() signal to the process() slot in the worker, causing it to start.
connect(captureThread, SIGNAL(started()), captureWorker, SLOT(process()));
// Connect worker finished signal to trigger thread quit, then delete.
connect(captureWorker, SIGNAL(finished()), captureThread, SLOT(quit()));
connect(captureWorker, SIGNAL(finished()), captureWorker, SLOT(deleteLater()));
// Make sure the thread object is deleted after execution has finished.
connect(captureThread, SIGNAL(finished()), captureThread, SLOT(deleteLater()));
// Give QThread ownership of Worker Object
captureWorker->moveToThread(captureThread);
captureThread->start();
}
CaptureWorker.cpp
void CaptureWorker::process()
{
while(true)
{
g_exit_lock->lockForRead();
if(g_exit)
{
g_exit_lock->unlock();
break;
}
g_exit_lock->unlock();
}
qDebug() << "CaptureWorker: Exiting.";
emit finished();
}
Теперь, когда я пытаюсь остановить поток, установив флаг верно в некоторой функции, то process() возвращает, но поток не заканчивается, и вызов wait() блокируется навсегда. Почему мой поток не заканчивается? Выход
g_exit_lock->lockForWrite();
g_exit = true;
g_exit_lock->unlock();
QThread::sleep(15);
qDebug() << "ct finished? " << captureThread->isFinished();
captureThread->wait();
qDebug() << "All threads stopped.";
Logfile:
2013.03.26 09:29:22[D] CaptureWorker: Exiting.
2013.03.26 09:29:37[D] ct finished? false
UPDATE
Я сделал некоторые отладки и выяснил некоторые межжала вещи:
- нити блоков в своем цикле обработки событий (QEventLoop :: Exec). Он ждет сигнала quit(), который, по-видимому, не получает.
- Создан цикл событий потока после process() возвращается. Подключив сигналы, как и я, метод run() потока вызывается после того, как поток уже завершил выполнение своей работы (например, process()).
- Цикл событий очищает все опубликованные события выхода до выполнения фактического цикла.
Мой вывод
- Подключение бросить курить() слот, как я не работает, потому что бросить курить() события удаляются, когда цикл событий устанавливается
- Вызов бросить курить член() функция непосредственно на объект потока, по-видимому, приводит к изящному завершению. Это можно сделать извне или изнутри с помощью QThread :: currentThread() -> quit();
Открытые вопросы
- Есть ли способ вызова метода процесса() после того, как цикл событий было установлено?
- Неправильно, что цикл событий создается, когда работа выполнена. Однако, как я использую QThread в соответствии с docs
Возможно, вам просто нужно очистить поток отладки? – Nick
Что такое готовое()? –
Регистрация - очень * непростой способ отладки программ. Узнайте, как использовать отладчик. Просто присоедините отладчик, сломайте программу, переключите контекст на рабочий поток и узнайте, что он делает из трассировки стека. С большими шансами, что вы теперь обнаружите, что он не выполняет цикл, но похоронен в каком-то OS-вызове, ожидая завершения захвата. Поэтому он не тестирует g_exit, поэтому он не уходит. –