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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Удаление объекта в потоке  (Прочитано 7073 раз)
Naihil
Новичок

Offline Offline

Сообщений: 23


Просмотр профиля
« : Май 12, 2011, 10:54 »

Здравстуйте!
После прочтения данных постов (http://labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong/ и http://labs.qt.nokia.com/2006/12/04/threading-without-the-headache/) решил переделать логику работы с потоком, но столкнулся с проблемой удаления объекта, помещаемого в поток.
Имеется:
Код:
class CMainWindow : public QMainWindow
{
    Q_OBJECT
.......
private:
    QThread mThread;
.......
};

CMainWindow::CMainWindow(QWidget *parent)
: QMainWindow(parent), mpUi(new Ui::CMainWindow)
{
.......
    mThread.start();

    CSomeClass *s = new CSomeClass;
    connect(&mThread, SIGNAL(finished()), s, SLOT(deleteLater()));

    s->moveToThread(&mThread);
.......
}

CMainWindow::~CMainWindow()
{
mThread.quit();
mThread.wait();
}
По логике, объект CSomeClass должен удаляться при завершении потока, но деструктор не вызывается. Подозреваю, что это всё из-за механизма QueuedConnection.
Как быть в такой ситуации?
Записан
mutineer
Гость
« Ответ #1 : Май 12, 2011, 10:56 »

удаление по deleteLater() вроде происходит в eventLoop потока, которому он принадлежит. Может дело в том, что eventLoop потока уже не работает, поэтому объект и не удаляется?
Записан
Naihil
Новичок

Offline Offline

Сообщений: 23


Просмотр профиля
« Ответ #2 : Май 12, 2011, 11:00 »

удаление по deleteLater() вроде происходит в eventLoop потока, которому он принадлежит. Может дело в том, что eventLoop потока уже не работает, поэтому объект и не удаляется?
Да, в документации по Qt::QueuedConnection так и написано, в этом-то и проблема. Объект в поток засунули, а как его удалить после этого?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Май 12, 2011, 11:30 »

Когда нитка испустит finished, с ее eventLoop уже покончено, поэтому до deleteLater дело не дойдет (если объект был перенесен с помощью moveToThread). Можно сделать слот где объект будет удаляться  и связать его с тем же finished. Хорошо бы смотрелось и создание объекта по сигналу started

Эти требует чуть больше строк, зато просто и надежно
Записан
Naihil
Новичок

Offline Offline

Сообщений: 23


Просмотр профиля
« Ответ #4 : Май 12, 2011, 12:06 »

Когда нитка испустит finished, с ее eventLoop уже покончено, поэтому до deleteLater дело не дойдет (если объект был перенесен с помощью moveToThread). Можно сделать слот где объект будет удаляться  и связать его с тем же finished. Хорошо бы смотрелось и создание объекта по сигналу started

Эти требует чуть больше строк, зато просто и надежно
Сделал следующим образом:
Код:
class CMainWindow : public QMainWindow
{
    Q_OBJECT
.......
private:
    QThread mThread;
    CSomeClass *mpS;
.......
};

CMainWindow::CMainWindow(QWidget *parent)
: QMainWindow(parent), mpUi(new Ui::CMainWindow)
{
.......
    connect(&mThread, SIGNAL(finished()), this, SLOT(deleteListener()));
.......
}

void CMainWindow::closeEvent(QCloseEvent * e)
{
on_actConnectToServer_toggled(false);
e->accept();
}

void CMainWindow::on_actConnectToServer_toggled( bool v )
{
if(v) {
mpS = new CSomeClass;
mpS->moveToThread(&mThread);

mThread.start();

} else {
mThread.quit();
mThread.wait();
}
}

void CMainWindow::deleteListener()
{
delete mpS;
}
Вроде работает, но правильно ли удалять объект, находящийся в другом потоке, пусть и уже остановленном?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Май 12, 2011, 12:25 »

Сделал следующим образом:
Работать наверное будет но мне лично не нравится Улыбающийся А вдруг toggled вызовется 2 раза подряд с true? И зачем задействовать closeEvent которое напрямую с ниткой не связано? У Вас есть очень удобное место для создания - сигнал started, а можно и по-простому сделать mpS членом класса нитки (создавать в конструкторе, удалять в деструкторе).

Вроде работает, но правильно ли удалять объект, находящийся в другом потоке, пусть и уже остановленном?
Нет никакого "находящегося", просто объект хранит указатель на нитку, который используется чтобы засылать события в eventLoop этой нитки - вот и все.
Записан
Naihil
Новичок

Offline Offline

Сообщений: 23


Просмотр профиля
« Ответ #6 : Май 12, 2011, 13:53 »

Работать наверное будет но мне лично не нравится Улыбающийся А вдруг toggled вызовется 2 раза подряд с true?
Хм, об этом не подумал, но ет можно переделать.
И зачем задействовать closeEvent которое напрямую с ниткой не связано?
если вызвать "on_actConnectToServer_toggled(false);" в деструкторе, то сигнал finished() не испускается и объект не удаляется. Это, конечно, лечится с помощью qApp->processEvents(), но как-то ет не очень)
а можно и по-простому сделать mpS членом класса нитки (создавать в конструкторе, удалять в деструкторе).
В данном случае придётся наследоваться от QThread, от чего я и хотел отказаться)

Наверно будет лучше создать объект 1 раз при запуске потока и удалять при сигнале destroyed() + слот для управления работой самого объекта
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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