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

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

Страниц: 1 [2] 3 4 5   Вниз
  Печать  
Автор Тема: Не отрабатывает QTimer::timeout()  (Прочитано 30689 раз)
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #15 : Октябрь 04, 2015, 01:03 »

Ожидаемо не помогло Грустный
А увеличивать таймаут пробовали, для проверки?
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #16 : Октябрь 04, 2015, 01:06 »

Пробовал. start(10) почти работает - периодически "залипает" одна из ниток, start(100) работает гарантированно. Но меня такой интервал не устраивает.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #17 : Октябрь 04, 2015, 01:10 »

Пробовал. start(10) почти работает - периодически "залипает" одна из ниток, start(100) работает гарантированно. Но меня такой интервал не устраивает.
Я так понимаю, вы хотите вызывать step сразу после запуска eventloop.
Попробуйте вместо таймера использовать QMetaObject::invokeMethod c Qt::QueueConnect.
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #18 : Октябрь 04, 2015, 01:12 »

Мне, в целом, нужно максимально часто выполнять определенный код в тот момент когда очередь событий потока пуста. Собственно, исходил из этого посыла в документации:
To make your application perform idle processing (i.e. executing a special function whenever there are no pending events), use a QTimer with 0 timeout.
start(0) для меня чрезмерен - комп начинает "пожирать" самого себя. Может есть другие способы, особенно учитывая следующее предложение оттуда же?
More sophisticated idle processing schemes can be achieved using processEvents().
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #19 : Октябрь 04, 2015, 01:14 »

Вот invokeMethod для этого хорошо подходит.
В методе step просто добавляйте вызов его же самого через invokeMethod+QueueConnection и таймер не понадобиться.
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #20 : Октябрь 04, 2015, 01:18 »

step() должен вызываться всякий раз когда нитке больше "нечего делать". В приведенном примере его полезная нагрузка опущена. Пробовал заменить QTimer на timerEvent - результат ровно тот же. С invokeMethod попробую.
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #21 : Октябрь 04, 2015, 01:26 »

Вроде бы с invoke, на первый взгляд, заработало. Old, спасибо большое. Завтра на свежую голову проверю тщательнее. Но, в любом случае, поведение, на мой взгляд, странное. Особенно с учётом того, что этот таймерный нюанс проявляется только в мультипроцессорных конфигурациях.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #22 : Октябрь 04, 2015, 10:03 »

Неясно в какой нитке выполняется QThread::step. Если в главной, то все вполне объяснимо - события таймера игнорируются если в данный момент выполняется обработка предыдущего
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #23 : Октябрь 04, 2015, 10:06 »

Неясно в какой нитке выполняется QThread::step.
Тут остается только сожалеть.  Строит глазки
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #24 : Октябрь 04, 2015, 10:42 »

Неясно в какой нитке выполняется QThread::step.
В своей собственной - в той же, которая "run()", именно для проверки этого факта выводился currentThreadId

события таймера игнорируются если в данный момент выполняется обработка предыдущего
Эта версия теоретически имеет право на жизнь, но почему эффект не проявляется на "бытовых" ПК, а только на "серверных"?
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #25 : Октябрь 04, 2015, 10:43 »

step() должен вызываться всякий раз когда нитке больше "нечего делать". В приведенном примере его полезная нагрузка опущена. Пробовал заменить QTimer на timerEvent - результат ровно тот же. С invokeMethod попробую.
Вот сейчас подумалось. Для такого поведения, возможно удобней будет в ните запустить step как основное задание, а в перерывах обрабатывать накопившиеся события.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #26 : Октябрь 04, 2015, 10:59 »

Эта версия теоретически имеет право на жизнь, но почему эффект не проявляется на "бытовых" ПК, а только на "серверных"?
Наверное и теоретически не имеет. Ну хорошо, допустим один раз был занят, пропустили. Но ведь придут следующие события того же таймера - кто-то да пробьется

Тогда варианты почему это происходит:

1) Нитка загружена постоянно т.е. в ее EventLoop все время есть события - а события таймера помещаются в  EventLoop только если там никого нет. Это можно проверить отключив нагрузку

2)  EventLoop еще не запущен когда таймаут истек. Ну опять-таки неясно, ведь будут еще события таймера.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #27 : Октябрь 04, 2015, 11:16 »

а события таймера помещаются в  EventLoop только если там никого нет. Это можно проверить отключив нагрузку
Используется DirectConnection, слоты вызываются напрямую, никаких событий таймера в очередь не кладется.
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #28 : Октябрь 04, 2015, 11:27 »

Вот сейчас подумалось. Для такого поведения, возможно удобней будет в ните запустить step как основное задание, а в перерывах обрабатывать накопившиеся события.
Меня самого эта корявость архитектуры несколько гложет. Суть в том, что Thread - это пул воркеров и полезный код нагрузки выглядит примерно так:
Код
C++ (Qt)
void Thread::step()
{
   for (bool flag = true; flag;) {
       flag = false;
       for (Worker *worker : m_workers) {
           if (worker->isStepReady()) {
               worker->step();
               yieldCurrentThread();
               flag = true;
           };
       }
   }
}
 
Особенность воркеров такова, что у них потребность в работе возникает в среднем 10 раз в секунду, а продолжительность выполнения одного шага воркера достаточно мала, так что забивать комп бесконечной проверкой "не созрел ли кто для работы" тоже не хочется. С другой стороны, при достаточно большом количестве воркеров (до 1024) текущая схема тоже не выглядит идеальной. Правильнее было бы потоку спать до момента появления необходимости работать ближайшему воркеру. Но кто его будет будить? Снова таймер?
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #29 : Октябрь 04, 2015, 11:31 »

1) Нитка загружена постоянно т.е. в ее EventLoop все время есть события - а события таймера помещаются в  EventLoop только если там никого нет.
Проверял без нагрузки - разницы нет.
И опять таки:
почему эффект не проявляется на "бытовых" ПК, а только на "серверных"?
Записан
Страниц: 1 [2] 3 4 5   Вверх
  Печать  
 
Перейти в:  


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