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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Баг или фича? (Событие таймера)  (Прочитано 9296 раз)
uriel
Гость
« : Декабрь 07, 2007, 14:20 »

Столкнулся с одной неприятной вещью.
Есть объект, у которого переопределено событие таймера. Из определённой функции таймер запускается методом startTimer(int).
От события таймера требуется, чтобы оно выполнялось целиком до того, как начнётся другое. Под линуксом всё работало замечательно, но когда собрал приложение под виндой, оказалось, что новое событие начинает работать ещё до завершения предыдущего.
Кто-нибудь что-нибудь про такое слышал? В каком направлении копать?
Записан
Mikor
Гость
« Ответ #1 : Декабрь 07, 2007, 14:39 »

Первый раз слышу. Можно попробовать поставить в обработчик QMutexLocker на всю функцию, и, соответственно QMutex в поля класса.
А вообще, в начало обработчика я бы поставил на время отладки qDebug() << GetCurrentThreadId(); т.к. не могут себя так вести объекты в главном потоке.
Записан
WW
Гость
« Ответ #2 : Декабрь 07, 2007, 15:41 »

Это нормально. Обработчик таймера - это callback функция и вызывается системой. Пришло прерывание от таймера - вызывается твоя функция. А там хоть полчаса из нее не выходи. Системе это по барабану.
Я обычно заводил какую-нить static переменную в этой функции. входишь - проверил ее состояние - взвел - работаешь сбросил. тонкий момент - в мютексе проверка и взвод переменной.
Записан
uriel
Гость
« Ответ #3 : Декабрь 07, 2007, 15:52 »

Ну static переменную я сразу прикрутил, вроде работает. Просто, по-моему, это не совсем изящное решение. Улыбающийся
Тогда соответственно возникает вопрос, почему же в линуксе всё работает нормально? Только что проверил - никакого наложения нет. Получается, что линукс просто успевает за отведённое время выполнить функцию, а виндовс нет?
Записан
WW
Гость
« Ответ #4 : Декабрь 07, 2007, 17:18 »

под линуксом не проверял, на выходных проверю, а под виндой - это так.
Записан
SLiDER
Гость
« Ответ #5 : Декабрь 08, 2007, 02:22 »

  оказалось, что новое событие начинает работать ещё до завершения предыдущего.

Быть такого не могет, ибо обработчик таймера всегда вызывается в одном потоке, поэтому пока один тик таймера не отработал, второй стоит в очереди.
Записан
uriel
Гость
« Ответ #6 : Декабрь 08, 2007, 07:50 »

Ну здравый смысл мне подсказывает то же самое.
Сделал просто. В начале функции написал:
Код:
qDebug() << "!" << event->timerId() << QThread::currentThreadId();
В конце:
Код:
qDebug() << "!!";
В итоге в консоле имею следующее:
!
!
!!
!
!!
!!
Ну и соответственно ид таймера и потока, которые всегда одинаковы.
Записан
Tonal
Гость
« Ответ #7 : Декабрь 08, 2007, 16:41 »

Похоже, в обработчике события ты вызываешь показ диалога, или напрямую App->processEvents().
Если да, то вполне понятно, что события приходят.
В винде события оконного таймера доставляются в той же очереди, что и остальные оконные события.
Мне почему-то казалось, что и в linux-е должно быть так же.

Решения зависят от задачи - можно прокидывать события приходящие не во время, а можно создавать из них очередь и обробатывать именно её.
Записан
uriel
Гость
« Ответ #8 : Декабрь 08, 2007, 21:12 »

Воистину, мой косяк, вызывается там qApp->processEvents(); Теперь всё понятно. Почему-то сразу и не сообразил, спасибо. Но всё равно занятно, почему поведение на различных платформах отличается. Может быть, стоит отписаться Троллям?
Записан
Dodge
Гость
« Ответ #9 : Декабрь 08, 2007, 23:55 »

Воистину, мой косяк, вызывается там qApp->processEvents(); Теперь всё понятно. Почему-то сразу и не сообразил, спасибо. Но всё равно занятно, почему поведение на различных платформах отличается. Может быть, стоит отписаться Троллям?
Причем тут платформа, просто судя по всему в одном случае обработчик успевал отработать до следующего таймаута, а в др нет.
Записан
Tonal
Гость
« Ответ #10 : Декабрь 09, 2007, 12:10 »

Но всё равно занятно, почему поведение на различных платформах отличается. Может быть, стоит отписаться Троллям?
Запостить тролям баг - дело святое!
Попробуй нарисовать минимальный воспроизводимый пример.
Запость сначала сюда - авось ещё какую-нибудь ляпу найдём.
Ну а если нет ляпов - можно и отправить. :-)
Записан
uriel
Гость
« Ответ #11 : Декабрь 09, 2007, 15:00 »

Да не вопрос, пожалуйста. Улыбающийся
Линукс терпиливо ждёт окончания for-а, а винда рвётся в бой. Подмигивающий
Код:
#include <QApplication>
#include <QDebug>
//
class test: public QObject
{
protected:
void timerEvent(QTimerEvent *ev)
{
qDebug() << "!" << ev->timerId();
for (int i=0; i<1000000; i++)
qApp->processEvents();
qDebug() << "!!" << ev->timerId();
}
};
//
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
test a;
a.startTimer(5);
return app.exec();
}
P.S. Для чистоты эксперемента использовал pro-файл, сделанный qmake -project.
P.P.S. Версия Qt - 4.3.2
Записан
Tonal
Гость
« Ответ #12 : Декабрь 09, 2007, 16:03 »

С виндой - понятно работает именно так, как я и предположил.
А с linux - не ясно. Это баг или так и должно быть. По исходникам я не понял, а в ассистенте нету.

Так что можно запостить - как минимум - баг документации.
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #13 : Декабрь 09, 2007, 17:52 »

имхо, нужно отослать репорт тролям. Интересно что они скажут.
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Alex03
Гость
« Ответ #14 : Декабрь 10, 2007, 08:05 »

имхо, нужно отослать репорт тролям. Интересно что они скажут.

Они скорее всего ничего не скажут, ибо всё работает так как и надо.
Если uriel сам себе создал проблемы с рекурсией, то при чём тут Qt и таймеры?
Ну а различия под разными платформами в данном случае - случайность, поизменяйте число 1000000 и в линуксе получите то же что и в винде.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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