LINUX.ORG.RU

Убить поток


0

0

Уважаемый ALL!
Опять взываю к вашей помощи!

Есть класс, унаследованный от QThread.
Данный класс запускается по нажатию на кнопку «Start» в GUI (название кнопки меняется на «Stop» и по нажатию на этот «Stop» все расчеты должны прекратиться).
из метода run вызывается go():

void ExtrThread::go(){
     emit started();

     /*SpiceExtr*/ *spe;
     spe= new SpiceExtr(path);
     connect(spe, SIGNAL(startModelChanging()), this, SLOT(MEdStarted()));
     connect(spe, SIGNAL(stopModelChanging()), this, SLOT(MEdStoped()));

     ........

     spe->MultiRun(dim, x, fx, result);

     emit stopped(cur);
     
}

Ф-я MultiRun - многократно запускает функцию для расчета. Помимо прочего вызываемая из MultiRun ф-я на каждой итерации читает и изменяет текстовый файл:
void SpiceExtr::setSpiceInputValues(string sl){
    emit startModelChanging();
	
..................................

        QFile new_f(QString::fromStdString(filename.c_str()));
        QFile old_f(QString::fromStdString(sl.c_str()));
        if(old_f.open(QIODevice::ReadWrite)){
            if(new_f.open(QIODevice::ReadWrite)){
                QTextStream in_stream( &old_f );
                QTextStream out_stream( &new_f );
                QString line;
                while(!in_stream.atEnd()){
		............................
		}
            }else{
                qDebug()<<"setSpiceInputValues NewFil Error\n";
                exit(0);
            }
        }else{
            qDebug()<<"setSpiceInputValues OldFil Error\n";
            exit(0);
        }
        old_f.close();
        new_f.close();

        if(old_f.remove()){

            if(!new_f.rename(QString::fromStdString(sl.c_str()))){
                qDebug()<<"Error file"<< QString::fromStdString(filename.c_str())<<" renaming failed\n";
                exit(0);
            }else {
            }
        }else{
        }
        emit stopModelChanging();
};
Теперь сам вопрос: Как мне правильно завершить выполнение данного потока. Если он завершается сам по себе, то его повторный вызов отлично работает. Если же его надо убивать (по нажатию на «Stop»), то при следующем вызове нету доступа к файлу.
setSpiceInputValues OldFil Error

Вот так я все убиваю:

void ExtrThread::kill(){

    if(yesToKill) {
        del();
        spe->deleteLater();
        delete spe;

        this->terminate();
        this->exit();
            }
}

А как правильно?
SpiceExtr изначально делался для консольного приложения, поэтому можно наследовать от чего угодно (пока это QObject).

З.Ы За помесь STL и QT прошу не ругать. Устрою субботник и все подправлю).

Ответ на: комментарий от spike_by

Имеется ввиду метод QThread::setTerminationEnabled, позволяющий явно указать, когда поток можно или нельзя прибивать. Вообще, это очень плохая практика.

mannaz
()
Ответ на: комментарий от mannaz

Хорошо, с другой стороны.
Почему, когда я удаляю переменную spe( а она вызывается уже из потока) то переменная для работы с файлом (QFile new_f(QString::fromStdString(filename.c_str()));) его не открывает.
При закрытии в ExtrThread ссылку на класс я удалил, а сама переменная (new_f класса SpiceExtr) у меня не глобальная, а локальная вообще. Как мне правильно сделать деструктор класса SpiceExtr.
Опять же с другой стороны:
в ф-и setSpiceInputValues я посылаю сигналы, которые меняют в ExtrThread булеву переменную yesToKill, делая ее false, пока функция работает с файлом. Почему это не помогает при закрытии потока?
Что происходит с new_f?

spike_by
() автор топика
Ответ на: комментарий от spike_by

Возможно сумбурно - простите.
Все это можно резюмировать так:
как мне корректно завершить работу итерационной ф-и класса (SpiceExtr) вызванной из класса-потока (ExtrThread). А то так как делаю я, вызывает проблему доступа к файлу при повторном запуске.

spike_by
() автор топика
Ответ на: комментарий от spike_by

>как мне корректно завершить работу итерационной ф-и класса (SpiceExtr) вызванной из класса-потока (ExtrThread). А то так как делаю я, вызывает проблему доступа к файлу при повторном запуске.

Не всегда подходящий вариант: ты не убивай поток, а меняй флаг какой-либо, чтобы он после итерации сам остановился. Правда если у тебя одна итерация долго выполняется, то этот вариант как минимум неудобен.

anonymous
()
Ответ на: комментарий от anonymous

Правда если у тебя одна итерация долго выполняется, то этот вариант как минимум неудобен.

В том то и дело, что долго считает;

spike_by
() автор топика
Ответ на: комментарий от placement_new

> Почему?

Например потому, что thread мог захватить какой-то ресурс. Если его убить, то ресурс не будет доступен вообще.

k_andy ★★★
()
Ответ на: комментарий от k_andy

Ну это из разряда ССЗБ. Я уж смотрю навреное куда точки прерываний то ставить.

placement_new ★★
()
Ответ на: комментарий от placement_new

> Почему?

Во-первых, сама тролло-нокия не рекомендует вызывать terminate() у объекта потока без веских на то причин; во-вторых на разных платформах setTerminationEnabled реализован по-разному: в венде cancellation point'ы «эмулируются» на уровне Qt, на системах, где есть pthread - используются вызовы pthread_setcancelstate, pthread_cancel и пр. (даже список блокирующих вызовов, которые являются cancellation point'ами, может варьироваться от системы к системе). Ну и наконец, на мой взгляд, принудительное завершение одного потока из другого - это error-prone и скорее всего кривое архитектурное решение. Это же C++, а не bash или erlang.

mannaz
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.