Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: iceBear от Июль 17, 2012, 14:32



Название: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: iceBear от Июль 17, 2012, 14:32
Здравствуйте,

На центральном виджете, который представляет собой экземпляр класса ImageViewer расположены 10 штук QgraphicsSimpleTextItem, которые получают данные из сторонних процессов. Каждый QgraphicsSimpleTextItem прикреплен к своему процессу. Процессы работают с большими скоростями - обновляя данные раз в 10 мс. Для каждого QgraphicsSimpleTextItem вызывается метод setText(), и обновленное состояние текстовок отображается на мониторе.

Приблизительно (каждый раз по разному) на 2000 итерации вся программа благополучно сваливается в ошибку. Возникает ощущение, при выполнении операции setText () для одного экземпляра QgraphicsSimpleTextItem происходит обновление всего центрального виджета,  и, соответственно, когда два потока пытаются одновременно обновить состояние своих QgraphicsSimpleTextItem,   ошибка и возникает.

Правильно ли я себе все представляю? Если да, то можно ли сделать так, чтобы обновление виджета делать принудительно (например вызывая вручную метод update ()), а не автоматически - при вызове QgraphicsSimpleTextItem::setText ()?


спасибо,


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: _OLEGator_ от Июль 17, 2012, 14:43
Вообще странно работать с GUI из потоков напрямую, должно сразу валиться приложение, с GUI надо работать из одного основного потока.


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: iceBear от Июль 17, 2012, 14:47
оно и валится почти сразу,

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

ограничить все одним потоком - рассматривается, но как самый запасной вариант


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: _OLEGator_ от Июль 17, 2012, 14:51
Данные мониторить можно в разных потоках, нельзя напрямую с GUI работать из не основного потока.
При обновлении данных необходимо информировать основной поток об изменениях, через механизм сигналов и слотов или механизм событий, помоему эта тема обсуждалась на форуме - поищите.


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: V1KT0P от Июль 17, 2012, 15:00
Вообще странно работать с GUI из потоков напрямую, должно сразу валиться приложение, с GUI надо работать из одного основного потока.
+1 Никто в здравом уме не будет работать с GUI с левых потоков. К тому же я не думаю что так уж необходимо обновлять визуальное отображение данных 100 раз в секунду. Складывай данные для обновления в буфер и обновляй раз или два в секунду через сигнал.


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Bepec от Июль 17, 2012, 15:12
Чуть поправлю виктора - не так уж необходимо обновлять view раз в 5 мс, достаточно 25 мс :)


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: V1KT0P от Июль 17, 2012, 15:16
Чуть поправлю виктора - не так уж необходимо обновлять view раз в 5 мс, достаточно 25 мс :)
40 раз в секунду? Даже видео 25 кадров в секунду смотрится нормально =).


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: iceBear от Июль 17, 2012, 15:28
спасибо большое за ответы,

про скорость - были случаи, когда на промышленных рентгенустановках приходилось регистрировать телеграммы с частотой 5 мс - такая скорость продиктована всего лишь точностью описания процесса,

если обновлять содержимое не 5 а 25 раз в секунду - софтина свалится в ошибку не на 2000,а на 15000 итерации - в данном случае все равно патология остается, как мне кажется, даже не уменьшается вероятность возникновения ошибки

напрямую из потоков, методы компонентов GUI я конечно не вызываю,



Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: V1KT0P от Июль 17, 2012, 15:35
спасибо большое за ответы,

про скорость - были случаи, когда на промышленных рентгенустановках приходилось регистрировать телеграммы с частотой 5 мс - такая скорость продиктована всего лишь точностью описания процесса,

если обновлять содержимое не 5 а 25 раз в секунду - софтина свалится в ошибку не на 2000,а на 15000 итерации - в данном случае все равно патология остается, как мне кажется, даже не уменьшается вероятность возникновения ошибки

напрямую из потоков, методы компонентов GUI я конечно не вызываю,
Может у тебя память течет и после 2000 не остается свободной? А что бэктрейс пишет?


Название: Re: одновременное обновление активных элем
Отправлено: _OLEGator_ от Июль 17, 2012, 15:40
напрямую из потоков, методы компонентов GUI я конечно не вызываю,
А как же QGraphicsSimpleTextItem::setText() ?!


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Bepec от Июль 17, 2012, 15:42
Я за 25 раз в секунду. Меньше смысла нет(человек разницы не заметит), больше - тоже.(кому оно надо, тормоза то)

Вам уже ясно сказали - нельзя работать с gui из разных потоков. Надо использовать сигнал-слотовое соединение.

iceBear - вы видно не можете сообразить.

 Регистрировать телеграммы, обрабатывать сигналы и прочая - вы можете хоть 100 раз в мс. А вот обновлять view достаточно раз в 25 мс.

Человеческий глаз не заметит мельканий раз в 5мс и прочего. Излишняя только работа.




Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: iceBear от Июль 17, 2012, 15:59
сигнал - слотовое соединение конечно же использую, это очевидно,

QGraphicsSimpleTextItem::setText () вызываю через него - т.е. поток генерирует сигнал, который обрабатывается уже в потоке главного приложения, часть обработки занимает setText (),

"...А вот обновлять view достаточно раз в 25 мс. Человеческий глаз не заметит мельканий раз в 5мс и прочего. Излишняя только работа." - раз в 25 мс тоже много, если ориентироваться на визуальное представление достаточно - 24 раз в секунду


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: iceBear от Июль 17, 2012, 16:05
вот еще вопрос в эту же тему - есть ли в QT событие OnIdle () или его аналог?

спасибо


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: V1KT0P от Июль 17, 2012, 16:10
Так что пишет бэктрейс при падении? Ибо наугад гадать где ошибка не годится.


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: iceBear от Июль 17, 2012, 16:14
это моя ошибка - не трассировал,

вываливает виндовое окно, что приложение выполнило недопустимую операцию и будет закрыто.

Из обработчиков убирал, все, что касается QGraphicsSimpleTextItem и при этом условии все работало надежно (проверял три часа - утечек памяти нет, скорости не уменьшаются)

 


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Bepec от Июль 17, 2012, 16:55
Проще выражаясь - ошибку вы локализовали. Она у вас в той части, ез которой работает усё ок.

Дебаггер в руки и вперед!

PS ну или выкладывайте код.


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Igors от Июль 17, 2012, 18:30
вот еще вопрос в эту же тему - есть ли в QT событие OnIdle () или его аналог?
QTimer с интервалом ноль.

Человеческий глаз не заметит мельканий раз в 5мс и прочего. Излишняя только работа.
Глаз и фотоны ловит, так что мелькание заметит. Другое дело что исходить надо из соображений плавности для чего 25 fps вполне гуд



Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: DmitryM от Июль 17, 2012, 20:13
вот еще вопрос в эту же тему - есть ли в QT событие OnIdle () или его аналог?
QTimer с интервалом ноль.
лучше такое не делать ;)


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Bepec от Июль 17, 2012, 20:27
Qtimer с интервалом в 0 напрямую вызывает функцию, минуя таймер и прочая, так что ничего плохого не случится.

PS Тролли фигней не особо страдали :)


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: mutineer от Июль 17, 2012, 20:27
вот еще вопрос в эту же тему - есть ли в QT событие OnIdle () или его аналог?
QTimer с интервалом ноль.
лучше такое не делать ;)

А можно аргументации? Интересно почему лучше такое не делать


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: DmitryM от Июль 19, 2012, 12:56
Qtimer с интервалом в 0 напрямую вызывает функцию, минуя таймер и прочая, так что ничего плохого не случится.

PS Тролли фигней не особо страдали :)
Да?
А это что:
Цитировать
The default value for this property is 0. A QTimer with a timeout interval of 0 will time out as soon as all the events in the window system's event queue have been processed.


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Bepec от Июль 19, 2012, 13:29
Это означает, что вызов функции будет добавлен в конец очереди сообщений окна. Проще выражаясь - прямой вызов функции.(правильный ответ в первом предложении)


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Igors от Июль 19, 2012, 14:17
Это означает, что вызов функции будет добавлен в конец очереди сообщений окна. Проще выражаясь - прямой вызов функции.
Прочитав этот пост я было подумал - ну щас ему дадут! "Не прочитал документацию!!!" и все такое.. Однако же - повешенная лапша успешно проходит  :)

Никаких там "прямых" вызовов нет - это событие генерируемое системой и добавляемое в eventLoop как и остальные (напр мышиные). Ну там "события таймера имеют низший приоритет и.т.п. - песня известная

Ну а почему "лучше этого не делать" я тоже не понял


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Bepec от Июль 19, 2012, 14:23
Igors, скажите пожалуйста, если поставить бесконечный цикл и вызвать напрямую функцию, куда она пойдёт? :)

Или вы скажете, что EventLoop ничего общего с очередью сообщений не имеет? Прошу, не сдерживайте себя, авось я чегой т полезного узнаю :D


update: исходнички форева :)

Цитировать
void QTimer::singleShot(int msec, QObject *receiver, const char *member)
{
    if (receiver && member) {
        if (msec == 0) {
            // special code shortpath for 0-timers
            const char* bracketPosition = strchr(member, '(');
            if (!bracketPosition || !(member[0] >= '0' && member[0] <= '3')) {
                qWarning("QTimer::singleShot: Invalid slot specification");
                return;
            }
            QByteArray methodName(member+1, bracketPosition - 1 - member); // extract method name
            QMetaObject::invokeMethod(receiver, methodName.constData(), Qt::QueuedConnection);
            return;
        }
        (void) new QSingleShotTimer(msec, receiver, member);
    }
}


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: mutineer от Июль 19, 2012, 14:43
update: исходнички форева :)

Ну да, постит сообщение в EventLoop. А под "прямой вызов" большинство программистов небезосновательно понимают вызов метода прям отсюда. Вызов при помощи сообщения в EventLoop это несколько другое же


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Bepec от Июль 19, 2012, 14:46
Ну таки да, погорячился с прямым вызовом, но ранее ответил правильно - ставит в очередь :)


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Igors от Июль 19, 2012, 14:56
Вот стек вызовов (аттач). Ясно видно что "ноги растут" от ОС (СFRun..), приложение получило событие от него. Причем здесь какой-то "прямой вызов"?


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Bepec от Июль 19, 2012, 15:09
Igors, да я немного оговорился про прямой вызов(сгоряча, не спорю :D ). В очередь сообщений ставит.

Смотри выше исходники.

Мб у вас система такая или я чего-то недопонимаю, но timeout'a при нулевом интервале у вас быть не должно. На винде 7 x64 во всяком случае, идёт обычный QMetaObject::invokeMethod.

Аналогично вызову слота с QueuedConnection. 


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Igors от Июль 19, 2012, 15:27
Мб у вас система такая или я чего-то недопонимаю, но timeout'a при нулевом интервале у вас быть не должно. На винде 7 x64 во всяком случае, идёт обычный QMetaObject::invokeMethod.
Должен быть, ведь идея в том что приложение получает idle когда нет др событий - значит хоть раз ОС должен "прокачать" события. Просто ставите break в слоте таймера и смотрите стек. А invokeMethod может иметь место, но только после того как событие получено от ОС. То уже личное дело Qt как распорядиться полученным


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Bepec от Июль 19, 2012, 15:30
Igors, повторюсь. Вы видимо не смотрели код.
Когда задаётся таймер с 0(нулевым) интервалом, идёт вызов  QMetaObject::invokeMethod.

Сигнал timeOut в данном случае не вызывается. Проверил только что на своей машине.
Если интервал более 0, то ставится обычный виндовый таймер.


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Igors от Июль 19, 2012, 15:51
Igors, повторюсь. Вы видимо не смотрели код.
Когда задаётся таймер с 0(нулевым) интервалом, идёт вызов  QMetaObject::invokeMethod.
Это Вы говорите о статическом методе (утилите) QTimer::singleShot. Но если Вы создали таймер с нулевым интервалом и сделали ему start, то событие будет получено через OC (даже если setSingleShot(true)).


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Bepec от Июль 19, 2012, 16:55
Если создать таймер и использовать метод singleShot - вызов пойдёт напрямую.

Если же использовать метод старт - в любом случае будет идти через систему.

Этого я незнал, хотя бы из здравого смысла - не могу представить себе необходимым таймер в цикле с нулевым интервалом - прямой путь в лагамМ :)


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Igors от Июль 19, 2012, 18:33
Если создать таймер и использовать метод singleShot - вызов пойдёт напрямую.
Зачем создавать экземпляр если singleShot статический?

Этого я незнал, хотя бы из здравого смысла - не могу представить себе необходимым таймер в цикле с нулевым интервалом - прямой путь в лагамМ :)
Это довольно популярный метод, многие приложения используют его (особенно что постарше). Эффект примерно тот же что и выполнение долгой операции в др потоке чтобы не замерзало UI. Плюсы в том что UI всегда под рукой, минусы - что единичная операция должна быть достаточно мелкой


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Bepec от Июль 19, 2012, 19:14
Вы открыли мне глаза. Я ж разбалован потоками и прочим :)


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: pastor от Июль 19, 2012, 19:33
Если создать таймер и использовать метод singleShot - вызов пойдёт напрямую.

Напрямую это как? ))


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Bepec от Июль 19, 2012, 19:58
pastor - исходник выложен на предыдущей странице :) Вы в нём поймёте больше, чем я могу рассказать :D


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: pastor от Июль 19, 2012, 20:15
pastor - исходник выложен на предыдущей странице :) Вы в нём поймёте больше, чем я могу рассказать :D

Ну я там как раз и не увидел "прямого вызова". Я думаю QueuedConnection должен вам намекнуть ))


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: DmitryM от Июль 19, 2012, 20:39
Ну а почему "лучше этого не делать" я тоже не понял
Образуется что-то типа forever, который работает через перегруженный EventLoop, т.е. на гране hotspot.


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Igors от Июль 19, 2012, 21:13
Образуется что-то типа forever, который работает через перегруженный EventLoop, т.е. на гране hotspot.
Ничего там не образуется, т.к. максимум 1 событие этого таймера может быть в EventLoop


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: pastor от Июль 19, 2012, 21:26
Причем этот ивент возникает исключительно тогда, когда event loop несодерджит других ивентов.


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Bepec от Июль 19, 2012, 21:57
Эх люди люди, когда ж читать начнёте? :)

PS для не понявших цель - прочитать тему с самого начала и прекратить перепост уже обсуждённых вопросов :D


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: DmitryM от Июль 20, 2012, 07:18
Причем этот ивент возникает исключительно тогда, когда event loop несодерджит других ивентов.
Цитировать
The default value for this property is 0. A QTimer with a timeout interval of 0 will time out as soon as all the events in the window system's event queue have been processed.
Написано же, что обработка начинается после обработки событий менеджера окон, значит эвент помещается в очередь.
Не вериться, смотри реализацию для того же Windows.

Эх люди люди, когда ж читать начнёте? :)

PS для не понявших цель - прочитать тему с самого начала и прекратить перепост уже обсуждённых вопросов :D
Вопрос был о существование OnIdle (http://msdn.microsoft.com/ru-ru/library/3e077sxt.aspx), на что Igors выдал QTimer с 0.

Вот QTimer с 0, который пожирает четверть процессора.
Код
C++ (Qt)
#include "widget.h"
#include "ui_widget.h"
 
Widget::Widget(QWidget *parent) :
   QWidget(parent),
   ui(new Ui::Widget)
{
   ui->setupUi(this);
 
   connect(&m_timer, SIGNAL(timeout()), this, SLOT(timeoutSlot()));
 
   m_timer.start(0);
}
 
void Widget::timeoutSlot()
{
   static size_t t = 0;
   t++;
}
 
Widget::~Widget()
{
   delete ui;
}
 
(http://img819.imageshack.us/img819/4163/testka.th.jpg) (http://imageshack.us/photo/my-images/819/testka.jpg/)


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Bepec от Июль 20, 2012, 07:29
ДмитрийМ - вы ещё создайте пустой указатель и попытайтесь в него писать по этому таймеру :D Будет очень оригинальный пример ошибок программирования :D

Вы в данном случае просто забиваете очередь событий пустым слотом. Если в слоте исполнялось бы что-нибудь затратное по времени, эффект был бы другой. Аналогичный образом работают потоки.

Создаёте поток с бесконечным циклом, пустым - будут те же 25%(100% загрузка одного ядра, как я понимаю :D). А если в цикл добавить действия, то сработает как надо.

А обсуждение началось с того, что
Цитировать
вот еще вопрос в эту же тему - есть ли в QT событие OnIdle () или его аналог?
QTimer с интервалом ноль.
лучше такое не делать

PS без здравого смысла любая программа может сожрать ваше процессорное время :D



Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: DmitryM от Июль 20, 2012, 11:03
Вы в данном случае просто забиваете очередь событий пустым слотом. Если в слоте исполнялось бы что-нибудь затратное по времени, эффект был бы другой.
Так ли это?  ;)
Подключай фантазию. Если этот код в GUI, то у тебя есть другие виджеты, который обрабатывают свои PaintEvent, MouseEvent и т. д. И все эти эвенты идут через очередь событий.


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Igors от Июль 20, 2012, 11:20
Вопрос был о существование OnIdle (http://msdn.microsoft.com/ru-ru/library/3e077sxt.aspx), на что Igors выдал QTimer с 0.
Да, и что не так?

Вот QTimer с 0, который пожирает четверть процессора.
У меня он пожирает одно ядро полностью - ну так и надо если планировались какие-то активные действия в idle. А нет - никто не мешает отключить или поставить больший интервал.

Вы в данном случае просто забиваете очередь событий пустым слотом.
Не забивает - сначала все полезные события проходят (UI не висит) и только если ничего нет - приходит timeOut


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: Bepec от Июль 20, 2012, 11:55
Согласен, Igors - я был неправ :)

PS незнал о таком полезном свойстве однако!


Название: Re: одновременное обновление активных элементов на центральном виджете приводит к ош
Отправлено: pastor от Июль 20, 2012, 12:04
Написано же, что обработка начинается после обработки событий менеджера окон, значит эвент помещается в очередь.
Не вериться, смотри реализацию для того же Windows.

Ну и в чем я неправ? Где я написал, что он не помещается в ивент луп? Ивент обработается после всех других событий ивент лупа. Ладно, немного перефразирую, то может не дошло:

"Ивент onidle возникнет тогда, когда очередь ивентов будет пуста".

Так ОК?