Поиск:

Ответ в темуСоздание новой темы Создание опроса
> QThread повисает или ошибка? Почему не отрабатывает terminate()? 
V
    Опции темы
null56
Дата 17.3.2009, 22:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 6
Всего: 12



В общем столкнулся со следующей проблемой, приведу упрощенный код (cpp):

Код

class thread : public QThread
{
public:
    thread();
    ~thread();

protected:
    void run();
};


Код

thread::thread()
{
}
thread :: ~thread()
{
    qDebug("wait thread: %d", QThread :: currentThread());
    terminate();
    qDebug("after terminate thread: %d", QThread :: currentThread());
    wait();
    qDebug("wait thread: %d", QThread :: currentThread());
}

void thread :: run()
{
    qDebug("thread: %d", QThread :: currentThread());
}

Собственно чего хочу добиться, чтобы перед удалением объекта Thread, дочерний поток (или функция run()) завершалась, а основной поток и в принципе это работает в большинстве случаев, но иногда все застревает на функции wait();
Код

main thread: 6540096
thread: 664888560
wait thread: 6540096
after terminate thread: 6540096
ВИСИМ!!!

Хотел поинтересоваться, возможен ли такой способ гарантированного завершения дочернего потока перед уничтожением самого объекта QThread или нет?
Для меня критична задача завершения этой функции, не важно в какой точке, за собой все почистят стековые объекты внутри функции run()...
Почему зависание происходит именно в точке wait? проблема в коде или в том, что я слишком часто запускаю подряд эту прогу, что какой - нибудь глобальный ресурс не освобождается, но это конечно маловероятно?
Или же такие вещи делать в деструкторе нельзя? хотя сама переменная локальная и тоже удаляется внутри функции, по идее отрабатывать должно

Заранее благодарен за помощь

Это сообщение отредактировал(а) null56 - 17.3.2009, 22:26
PM MAIL   Вверх
pan2004
Дата 17.3.2009, 22:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 357
Регистрация: 28.7.2007

Репутация: 6
Всего: 9



Цитата(null56 @  17.3.2009,  22:16 Найти цитируемый пост)
за собой все почистят стековые объекты внутри функции run()..

сомнительно, имхо:
Цитата

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.

Вообще, эта функция довольно опасна, и лучше по возможности обойтись без нее(например, устанавливать при выходе флаг завершения потока, который периодически проверять в run()).


--------------------
Qt4/C++ fan
WinXP SP3: MSVC++2005 Qt4.5.1 Boost1.39
сыграем в дурака?
PM MAIL   Вверх
null56
Дата 17.3.2009, 23:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 6
Всего: 12



я делал изначально без нее, пытаясь завершить eventloop внутри потока, так там все упиралось в то, что вызов завершения обработчика событий quit() проихоил после того, как запускался сам exec() и потом все зависало на том же wait, так как из exec() уже выйти было никак... что - то типа такого было...
Код

Thread :: ~Thread()
{
      quit();
      wait();
}

Thread :: run()
{
      MyEventLoop event_loop;
      event_loop.exec();
      // в деструкторе моего обработчика событий происходила необходимая мне очистка
}


Вышеприведенный код, судя по отладочной печати запускал евент луп между вызовом quit и wait(); но опять ж не всегда.... 
Кто - нибудь придумывал способы, которые бы тормозили основной поток до того момента пока не запускался бы поток или в случае разрушения,  останавливался???


Это сообщение отредактировал(а) null56 - 17.3.2009, 23:40
PM MAIL   Вверх
Acer
Дата 18.3.2009, 00:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 652
Регистрация: 5.9.2007
Где: UA::DN

Репутация: 15
Всего: 8



Все, что находится не в методе
Код

public:
        void run();

запускается в родительском(главном) потоке. Все, что в методе
Код

public:
        void run();

запускается в дочернем потоке.
Код

thread :: ~thread()
{
    qDebug("wait thread: %d", QThread :: currentThread());
    terminate(); /* перемести это в метод run() , если нужно убить дочерний поток */
    qDebug("after terminate thread: %d", QThread :: currentThread());

    wait(); /*вот тут ты "вешаешь" основной поток*/

    qDebug("wait thread: %d", QThread :: currentThread());
}

PM MAIL   Вверх
null56
Дата 18.3.2009, 00:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 6
Всего: 12



Код

 terminate(); /* перемести это в метод run() , если нужно убить дочерний поток */

А разьве не для того этот метод, чтобы как раз аварийно выйти из функции run, если верить тебе, что убить дочерний поток вообще нельзя из родительского?

ну вот смотри, допустим фрагмент кода из мейна
Код

Thread thread;
thread.start();
thread.terminate();
thread.wait();

Разьве это аналогично тому, что я делал в деструкторе класса Thread?
PM MAIL   Вверх
Acer
Дата 18.3.2009, 01:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 652
Регистрация: 5.9.2007
Где: UA::DN

Репутация: 15
Всего: 8



Возможно, я не правильно понял проблему.

Добавлено через 7 минут и 3 секунды
Смотри, если делать так, как ты писал
Код

thread::thread()
{
}
thread :: ~thread()
{
    qDebug("wait thread: %d", QThread :: currentThread());
    terminate();
    qDebug("after terminate thread: %d", QThread :: currentThread());
    wait();
    qDebug("wait thread: %d", QThread :: currentThread());
}
void thread :: run()
{
    qDebug("thread: %d", QThread :: currentThread());
}

Тут же завершается поток до того, как будет вызван деструктор. Так? То есть звершать уже нечего. И terminate() просто не сработает. А вот wait() повесит основной поток на ULONG_MAX, то есть на бесконечность.
Цитата

time milliseconds has elapsed. If time is ULONG_MAX (the default), then the wait will never timeout (the thread must return from run()). This function will return false if the wait timed out.


Добавлено через 14 минут и 16 секунд
Только что поробовал так же сделать... Через раз зависает...
Цитата

d:\xCPR\TestQt\debug>TestQt.exe
not terminated
return
destructor
//нормально отработало
d:\xCPR\TestQt\debug>TestQt.exe
not terminated
return
^C  //завис
d:\xCPR\TestQt\debug>TestQt.exe
not terminated
return
thread
^C //завис
d:\xCPR\TestQt\debug>
d:\xCPR\TestQt\debug>TestQt.exe
not terminated
return
destructor
//нормально отработало
d:\xCPR\TestQt\debug>TestQt.exe
not terminated
return
destructor
//нормально отработало
d:\xCPR\TestQt\debug>

вот с таким кодом:
Код

class thread: public QThread {
public:
    thread(){
    };
    ~thread(){
        terminate();
        qDebug() << "destructor";
        wait();
    };
public:
    void run(){
//        for ( long i = 0; i < 1000000000; i++ ){
        qDebug() << "thread";
//        }
    };
};

int main(int argc, char *argv[]){
    QApplication app( argc, argv );
    thread t;
    t.start();
    //system( "pause" );
    //t.terminate();
    if ( !t.isRunning() ){
        qDebug() << "terminated";
    } else {
        qDebug() << "not terminated";
    }
    qDebug() << "return";
    return 0;
}

PM MAIL   Вверх
Acer
Дата 18.3.2009, 01:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 652
Регистрация: 5.9.2007
Где: UA::DN

Репутация: 15
Всего: 8



Нашел кое-что. link
Пишут, что если в собственном деструкторе убивать поток, то ничего не произойдет.
PM MAIL   Вверх
null56
Дата 18.3.2009, 10:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 6
Всего: 12



Да, похоже на то....
А нет стандартных средств заставить родительский поток ждать пока дочерний поток не запустится?
все бы намного упростилось...
PM MAIL   Вверх
null56
Дата 18.3.2009, 13:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 6
Всего: 12



Сделал в start()
Код

        QThread :: start();
    while (!isRunning())
        { QThread::sleep(1); }


а в деструкторе
Код

    quit();
    wait();


Хорошее ли решение? хотя вероятность того, что поток стартует, но не успеет войти в eventloop до того, как в деструкторе будет вызван quit, но войдет в wait(), конечно остается, но вероятность мала....

Добавлено через 10 минут и 23 секунды
в деструкторе поправил
Код

{ quit(); } while (!wait(250))

Не очень красиво, но зато наверняка наверное?
PM MAIL   Вверх
Vaulter
Дата 18.3.2009, 15:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1724
Регистрация: 30.12.2002
Где: бункер

Репутация: нет
Всего: 22



буду писАть на коленке
Код

thread::run() {

    obj1 = new Object();

    while ( !this->alarm ) {
           // ...doing somthg


           ///....
    }


    delete obj1;

}

thread::~thread()        {

    this->alarm = true;
    wait();// здесь мы должны подождать столько времени, 
// чтобы хватило хотя бы на одну итерацию цикла while в run()


.....
}




--------------------
PM MAIL WWW ICQ   Вверх
null56
Дата 18.3.2009, 16:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 6
Всего: 12



ну да, суть ясна, спасибо...

Просто у меня все на eventloop завязано
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets"
JackYF
Любитель
  • В заголовке темы в квадратных скобках обозначьте используемую вами библиотеку, например: [QT],[GTK],[wx].
  • Если вопрос актуален только для некоторой версии библиотеки, либо, если вы пользуетесь не самой последней версией, укажите это. Например: [QT4], [GTK2].
  • Все начинающие изучать Qt - не забудьте зайти сюда.
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • В вопросе укажите полную версию версию библиотеки, а также все дополнительные используемые программные пакеты.
  • Не забывайте пользоваться кнопкой "Код".
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема »


 




[ Время генерации скрипта: 0.0487 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.