Russian Qt Forum
Ноябрь 27, 2024, 07:05 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Завершение QThread  (Прочитано 14426 раз)
skydion
Гость
« : Март 12, 2010, 10:39 »

Собственно вопрос, как правильно прекращать работу треда...?
У меня запускается тред на сканирование файлов, ну все это дело долгое,
поэтому нужно из интерфейса завершать тред, сейчас делал просто

Код:
bool MainWindow::stopScan()
{
if (thread)
{
thread->terminate();
thread->wait(500);
qDebug("Thread terminated");

delete thread;
}
}

почитал про треды и там есть предупреждение

]void QThread::terminate ()
Warning: This function is dangerous and its use is discouraged.

Записан
hackoff
Гость
« Ответ #1 : Март 12, 2010, 11:05 »

thread->exit(0);
thread->deleteLater();
Записан
skydion
Гость
« Ответ #2 : Март 12, 2010, 11:14 »

я так понимаю Вашим кодом заменить этот код?

thread->terminate();
thread->wait(500);

а как проверить завершился ли поток?
чтобы сделать изменения в интерфейсе? разблокировать заблокировать кнопки?
раньше я делал через перехват сигнала terminated (), а теперь finished () ловить?
« Последнее редактирование: Март 12, 2010, 11:21 от skydion » Записан
skydion
Гость
« Ответ #3 : Март 12, 2010, 12:26 »

теперь вот така фигня вылазит...

QObject::killTimers: timers cannot be stopped from another thread чем лечить?

Код:
MainWindow::MainWindow
{
    thread = new ScanThread(this);
}

void MainWindow::scanVocabulary(void)
{
    if (thread)
    {
thread->start(QThread::NormalPriority);

ui->pushButtonStart->setDisabled(true);
ui->pushButtonStop->setDisabled(false);

qDebug("scanVocabulary: Scan thread started");
    }
}

void MainWindow::stopScan()
{
    if (thread)
    {
thread->exit(0);
thread->deleteLater();

ui->pushButtonStart->setDisabled(false);
ui->pushButtonStart->setChecked(false);
    }
}

ScanThread::~ScanThread()
{
    if (!isRunning())
return;

    if (text.count())
    {
drv->beginTransaction();
query.addBindValue(text);
query.execBatch(QSqlQuery::ValuesAsRows);

le = query.lastError();
if (le.type() == QSqlError::NoError)
   drv->commitTransaction();
else
   qDebug() << "~ScanThread: [" << le.text() << "]";

query.finish();
    }

    wait(500);
}
Записан
alexman
Гость
« Ответ #4 : Март 12, 2010, 12:38 »

Замени
Код:
thread->exit(0);
thread->deleteLater();
на
Код:
thread->wait();
delete thread;
Записан
alexman
Гость
« Ответ #5 : Март 12, 2010, 12:54 »

Кстати,
Код:
void MainWindow::stopScan()
{
    if (thread)
    {
thread->exit(0);
thread->deleteLater();

ui->pushButtonStart->setDisabled(false);
ui->pushButtonStart->setChecked(false);
    }
}
к этому моменту поток уже знает, что ему нужно завершиться? Если нет, то перед этим ему нужно отправить сигнал, чтобы он завершился.
Записан
skydion
Гость
« Ответ #6 : Март 12, 2010, 13:25 »

Замени
Код:
thread->exit(0);
thread->deleteLater();
на
Код:
thread->wait();
delete thread;

вначале у меня так было... смотри начало треда...
Записан
skydion
Гость
« Ответ #7 : Март 12, 2010, 13:28 »

Кстати,
к этому моменту поток уже знает, что ему нужно завершиться? Если нет, то перед этим ему нужно отправить сигнал, чтобы он завершился.

как он может знать? какой сигнал ему послать?
я его хочу принудительно остановить, притом корректно (мне еще при завершении треда надо буфер скинуть в БД)
Записан
alexman
Гость
« Ответ #8 : Март 12, 2010, 13:40 »

Из потока нельзя принудительно завершать другой поток!
terminate() -> Warning: This function is dangerous and its use is discouraged. The thread can be terminate at any point in its code path. Threads can be terminated while modifying data. There is no chance for the thread to cleanup after itself, unlock any held mutexes, etc. In short, use this function only if absolutely necessary.

Тебе нужно как-нибудь уведомить о завершении другой поток из главного; например, послать сигнал canceled(), по сигналу сделать cancel = true, а далее
Цитировать
void run ()
{
    while(...) {
    ...
        if ( cancel ) {
            return;
        }
    ...
    }
}
Записан
alexman
Гость
« Ответ #9 : Март 12, 2010, 13:42 »

Ну а далее в главном потоке уже можно вызвать
Цитировать
thread->wait();
delete thread;
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Март 12, 2010, 13:43 »

как он может знать? какой сигнал ему послать?
я его хочу принудительно остановить, притом корректно (мне еще при завершении треда надо буфер скинуть в БД)
Принудительно не надо - можно нарваться на неприятности. Нитка завершится когда она выйдет из своего метода run - Вам надо каким-то образом сказать ей когда выходить. Напр. если нитка крутит EventLoop, сделайте ей quit. Если нитка занимается чисто расчетами - сделайте ей флажок типа FlagStop и проверяйте его в расчетах. После этого цивильно ждите завершения: thread->wait(); а можно и подсесть на сигнал нитки terminated()
Записан
skydion
Гость
« Ответ #11 : Март 12, 2010, 13:51 »

спасибо Вам, щас все осмыслю и буду ваять, много инфы навалилось  Смеющийся
Записан
ieroglif
Гость
« Ответ #12 : Март 12, 2010, 13:57 »

Код:
ThreadClass * thrd = new ThreadClass();
connect(thrd ,SIGNAL(finished()),thrd ,SLOT(deleteLater()));
thrd->start();
ну а внутри треда держать переменную булевскую и создать слот по её изменению.
Записан
skydion
Гость
« Ответ #13 : Март 12, 2010, 16:26 »

Всем спасибо, все решилось положительно Улыбающийся
Записан
Djavdet
Гость
« Ответ #14 : Апрель 13, 2010, 13:49 »

как конкретно?
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.123 секунд. Запросов: 23.