Russian Qt Forum

Qt => Общие вопросы => Тема начата: uriel от Декабрь 07, 2007, 14:20



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


Название: Re: Баг или фича? (Событие таймера)
Отправлено: Mikor от Декабрь 07, 2007, 14:39
Первый раз слышу. Можно попробовать поставить в обработчик QMutexLocker на всю функцию, и, соответственно QMutex в поля класса.
А вообще, в начало обработчика я бы поставил на время отладки qDebug() << GetCurrentThreadId(); т.к. не могут себя так вести объекты в главном потоке.


Название: Re: Баг или фича? (Событие таймера)
Отправлено: WW от Декабрь 07, 2007, 15:41
Это нормально. Обработчик таймера - это callback функция и вызывается системой. Пришло прерывание от таймера - вызывается твоя функция. А там хоть полчаса из нее не выходи. Системе это по барабану.
Я обычно заводил какую-нить static переменную в этой функции. входишь - проверил ее состояние - взвел - работаешь сбросил. тонкий момент - в мютексе проверка и взвод переменной.


Название: Re: Баг или фича? (Событие таймера)
Отправлено: uriel от Декабрь 07, 2007, 15:52
Ну static переменную я сразу прикрутил, вроде работает. Просто, по-моему, это не совсем изящное решение. :)
Тогда соответственно возникает вопрос, почему же в линуксе всё работает нормально? Только что проверил - никакого наложения нет. Получается, что линукс просто успевает за отведённое время выполнить функцию, а виндовс нет?


Название: Re: Баг или фича? (Событие таймера)
Отправлено: WW от Декабрь 07, 2007, 17:18
под линуксом не проверял, на выходных проверю, а под виндой - это так.


Название: Re: Баг или фича? (Событие таймера)
Отправлено: SLiDER от Декабрь 08, 2007, 02:22
  оказалось, что новое событие начинает работать ещё до завершения предыдущего.

Быть такого не могет, ибо обработчик таймера всегда вызывается в одном потоке, поэтому пока один тик таймера не отработал, второй стоит в очереди.


Название: Re: Баг или фича? (Событие таймера)
Отправлено: uriel от Декабрь 08, 2007, 07:50
Ну здравый смысл мне подсказывает то же самое.
Сделал просто. В начале функции написал:
Код:
qDebug() << "!" << event->timerId() << QThread::currentThreadId();
В конце:
Код:
qDebug() << "!!";
В итоге в консоле имею следующее:
!
!
!!
!
!!
!!
Ну и соответственно ид таймера и потока, которые всегда одинаковы.


Название: Re: Баг или фича? (Событие таймера)
Отправлено: Tonal от Декабрь 08, 2007, 16:41
Похоже, в обработчике события ты вызываешь показ диалога, или напрямую App->processEvents().
Если да, то вполне понятно, что события приходят.
В винде события оконного таймера доставляются в той же очереди, что и остальные оконные события.
Мне почему-то казалось, что и в linux-е должно быть так же.

Решения зависят от задачи - можно прокидывать события приходящие не во время, а можно создавать из них очередь и обробатывать именно её.


Название: Re: Баг или фича? (Событие таймера)
Отправлено: uriel от Декабрь 08, 2007, 21:12
Воистину, мой косяк, вызывается там qApp->processEvents(); Теперь всё понятно. Почему-то сразу и не сообразил, спасибо. Но всё равно занятно, почему поведение на различных платформах отличается. Может быть, стоит отписаться Троллям?


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


Название: Re: Баг или фича? (Событие таймера)
Отправлено: Tonal от Декабрь 09, 2007, 12:10
Но всё равно занятно, почему поведение на различных платформах отличается. Может быть, стоит отписаться Троллям?
Запостить тролям баг - дело святое!
Попробуй нарисовать минимальный воспроизводимый пример.
Запость сначала сюда - авось ещё какую-нибудь ляпу найдём.
Ну а если нет ляпов - можно и отправить. :-)


Название: Re: Баг или фича? (Событие таймера)
Отправлено: uriel от Декабрь 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


Название: Re: Баг или фича? (Событие таймера)
Отправлено: Tonal от Декабрь 09, 2007, 16:03
С виндой - понятно работает именно так, как я и предположил.
А с linux - не ясно. Это баг или так и должно быть. По исходникам я не понял, а в ассистенте нету.

Так что можно запостить - как минимум - баг документации.


Название: Re: Баг или фича? (Событие таймера)
Отправлено: pastor от Декабрь 09, 2007, 17:52
имхо, нужно отослать репорт тролям. Интересно что они скажут.


Название: Re: Баг или фича? (Событие таймера)
Отправлено: Alex03 от Декабрь 10, 2007, 08:05
имхо, нужно отослать репорт тролям. Интересно что они скажут.

Они скорее всего ничего не скажут, ибо всё работает так как и надо.
Если uriel сам себе создал проблемы с рекурсией, то при чём тут Qt и таймеры?
Ну а различия под разными платформами в данном случае - случайность, поизменяйте число 1000000 и в линуксе получите то же что и в винде.


Название: Re: Баг или фича? (Событие таймера)
Отправлено: Tonal от Декабрь 10, 2007, 11:02
Э... за 5 имллисекунд прокрутить милионный цикл - не слишком ли мощная машина должна быть у uriel?

Да и "проблем с рекурсией" тут нет - есть существенно разное поведение элементарного куска кода.


Название: Re: Баг или фича? (Событие таймера)
Отправлено: uriel от Декабрь 10, 2007, 12:13
Да дело тут не в милионном цикле. Это исключительно ради демонстрации различного поведения. Просто ожидается _одинаковое_ поведение кода под разными платформами, чему и противоречит данный пример.
P.S. Троллям отписался - посмотрим.


Название: Re: Баг или фича? (Событие таймера)
Отправлено: Alex03 от Декабрь 10, 2007, 13:01
Да дело тут не в милионном цикле. Это исключительно ради демонстрации различного поведения. Просто ожидается _одинаковое_ поведение кода под разными платформами, чему и противоречит данный пример.
P.S. Троллям отписался - посмотрим.

Т.е. Вы утверждаете что в винде события от одного таймера могут быть рекурсивными (с qApp->processEvents() в обработчике) а в линуксе нет? (не могу сейчас проверить под линухом.)
Даже если так то не вижу в этом криминала ибо поведение в винде вполне правильное, вот если бы они гарантировали иное (то как в линухе) то это конечно надо описывать в доках.


Название: Re: Баг или фича? (Событие таймера)
Отправлено: uriel от Декабрь 10, 2007, 17:32
Довольно оперативно ответили.
Про такой баг им уже сообщали. Если интересно, то вот линк с подробным описанием проблемы:
http://trolltech.com/developer/task-tracker/index_html?method=entry&id=183532
Запланировано на 4.4.0