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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: [решено] Как зачистить QObject из другого потока?  (Прочитано 13255 раз)
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« : Апрель 23, 2010, 15:48 »

Не могу его никак удалить.
Есть дочерний поток класса-наследника QThread и пара дополнительных методов:
Код
C++ (Qt)
void MyClass::run()
{
this->signalMapper = new QSignalMapper();
...
this->addNewTimer();
}
 
void MyClass::addNewTimer()
{
QTimer* timer = new QTimer();
QObject::connect(timer, SIGNAL(timeout()), this->signalMapper, SLOT(map()));
this->signalMapper->setMapping(timer, timer);
}
 

Далее маппер соединён со слотом delTimer(), чтобы при timeout() каждого таймера вызывался именно он:

Код
C++ (Qt)
void myClass::delTimer(QObject* timer)
{
// timer->moveToThread(this);
// timer->setParent(0);
// timer->moveToThread(this->thread());
// delete timer;
}
 

Пробовалось всё что закомментировано и не только это, но остальное посчитал лишним.
Ошибка: QObject::killTimer: timers cannot be stopped from another thread
Вот, хотелось бы узнать как удалить этот timer...
« Последнее редактирование: Апрель 23, 2010, 16:54 от serg_hd » Записан

kubuntu/Win7/x64/NetBeans
Kolobok
Гость
« Ответ #1 : Апрель 23, 2010, 15:55 »

А deleteLater не подходит?
Записан
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #2 : Апрель 23, 2010, 16:03 »

если
Код
C++ (Qt)
void myClass::delTimer(QObject* timer)
{
qDebug() << "text";
timer->deleteLater();
}
 
то текст действительно выводится только 1 раз, т.е. таймер сигнала больше не испускает. Но:
1) немного непонятен смысл - когда именно он удалится, ведь память выделялась вручную, не хотелось бы никакой утечки.
2) а если бы хотел удалить "нормальным" способом, то как?
« Последнее редактирование: Апрель 23, 2010, 16:07 от serg_hd » Записан

kubuntu/Win7/x64/NetBeans
SABROG
Гость
« Ответ #3 : Апрель 23, 2010, 16:13 »

1) немного непонятен смысл - когда именно он удалится, ведь память выделялась вручную, не хотелось бы никакой утечки.
Как только управление вернется в цикл событий, обычно это происходит после возврата из метода в котором вызвал deleteLater().

2) а если бы хотел удалить "нормальным" способом, то как?
После moveToThread() объект невозможно вернуть обратно в поток, где он создавался. Поэтому и удалять надо в том потоке в который его переместили. А если не перемещали, то в том потоке, где создавали.
Записан
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #4 : Апрель 23, 2010, 16:22 »

в том-то и дело, что если:
Код
C++ (Qt)
void myClass::delTimer(QObject* timer)
{
timer->moveToThread(this);
delete timer;
}
 

то будет ошибка: "QObject::killTimer: timers cannot be stopped from another thread".
А если
Код
C++ (Qt)
void myClass::delTimer(QObject* timer)
{
timer->moveToThread(this->thread());
delete timer;
}
 

то "QObject::moveToThread: Current thread (0x11680898) is not the object's thread (0x3d6a68). Cannot move to target thread (0x3d6a68)".
timer->setParent(0); ситуацию не меняет. Интересно всё-таки, наверняка когда-нибудь придётся удалять через delete.
Записан

kubuntu/Win7/x64/NetBeans
BRE
Гость
« Ответ #5 : Апрель 23, 2010, 16:29 »

В том месте, где делаешь соединение со слотом void MyClass::addNewTimer() задай тип подключения Qt::QueuedConnection.
Или ты его только из run вызываешь?
Записан
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #6 : Апрель 23, 2010, 16:34 »

В том месте, где делаешь соединение со слотом void MyClass::addNewTimer() задай тип подключения Qt::QueuedConnection.
Или ты его только из run вызываешь?

Да, слотом является только delTimer.
Записан

kubuntu/Win7/x64/NetBeans
SABROG
Гость
« Ответ #7 : Апрель 23, 2010, 16:35 »

Код
C++ (Qt)
this->addNewTimer();
 

У тебя таймер создается в отдельном потоке, зачем ему делать moveToThread?
Записан
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #8 : Апрель 23, 2010, 16:37 »

Код
C++ (Qt)
this->addNewTimer();
 

У тебя таймер создается в отдельном потоке, зачем ему делать moveToThread?
потому что удаляется он уже в другом. И неужто я бы сначала не попробовал удалить его без перемещения? Улыбающийся
Записан

kubuntu/Win7/x64/NetBeans
Kolobok
Гость
« Ответ #9 : Апрель 23, 2010, 16:39 »

У таймера какая задача? Себя уничтожить?
Записан
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #10 : Апрель 23, 2010, 16:41 »

У таймера какая задача? Себя уничтожить?
нет, это у слота для маппера такая задача - уничтожать таймер когда тот испускает таймаут. Естественно реальная задача другая, тут вынес очень урезанный код, чтобы людей не путать. Но смысл остался.
« Последнее редактирование: Апрель 23, 2010, 16:44 от serg_hd » Записан

kubuntu/Win7/x64/NetBeans
SABROG
Гость
« Ответ #11 : Апрель 23, 2010, 16:46 »

С таймерами между потоками совсем другая история нежели с обычным QObject'ом. Сомневаюсь, что тут moveToThread() поможет. Как бы троллям не пришлось писать, чтобы запретили перенос таймеров между потоками.
Записан
BRE
Гость
« Ответ #12 : Апрель 23, 2010, 16:46 »

Т.е. код можно упростить так:
Код
C++ (Qt)
void MyClass::run()
{
this->signalMapper = new QSignalMapper();
...
QTimer* timer = new QTimer();
QObject::connect(timer, SIGNAL(timeout()), this->signalMapper, SLOT(map()));
this->signalMapper->setMapping(timer, timer);
}
 

Правильно?

Если да, то удалять таймер нужно через deleteLater, т.к. сам таймер является инициатором этого сигнала и используется подключение Qt::DirectConnection.
Никаких moveToThread не нужно, все и так в одном потоке создается.
Записан
Kolobok
Гость
« Ответ #13 : Апрель 23, 2010, 16:49 »

В том слоте, который вызывается, нужен этот таймер?
Записан
serg_hd
Хакер
*****
Offline Offline

Сообщений: 668



Просмотр профиля
« Ответ #14 : Апрель 23, 2010, 16:51 »

Т.е. код можно упростить так:
Код
C++ (Qt)
void MyClass::run()
{
this->signalMapper = new QSignalMapper();
...
QTimer* timer = new QTimer();
QObject::connect(timer, SIGNAL(timeout()), this->signalMapper, SLOT(map()));
this->signalMapper->setMapping(timer, timer);
}
 
Правильно?
Да, так и есть. Но я решил вынести в отдельный метод, т.к. в ране было бы слишком много кода (в реальности картина по объёмнее), но суть та же.
Записан

kubuntu/Win7/x64/NetBeans
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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