Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.77/13: Рейтинг темы: голосов - 13, средняя оценка - 4.77
1 / 1 / 0
Регистрация: 24.02.2014
Сообщений: 45

Отрисовка потоком в Canvas

05.07.2016, 20:53. Показов 2628. Ответов 23
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток. В общем ситуация такова: есть таймер, работающий с точностью в 10мс в отдельном потоке. В зависимости от времени, на канве рисуются графики и куча другого динамического интерфейса. В программе есть два режима работы: непрерывный и дискретный. Дискретный заканчивает отрисовку каждые 1570 мс, после чего пользователь должен нажать кнопку "продолжить" и работа таймера и отрисовки возобновляется. Однако, я столкнулся с рядом проблем.

В общем если рисовать на канве в отдельном потоке, то интерфейс начинает сильно глючить. Приходится ставить задержку в 10мс, но тут проявляется другая проблема, которая заключается в плохой синхронизации. Иногда программа не успевает отловить нужное значение времени в потоке, и в дискретном режиме работы отрисовка не прекращается. Есть какие-нибудь идеи или советы по решению данной проблемы? Понимаю, что работа с интерфейсом должна происходить в основном потоке, но отрисовка циклами заставляет программу зависать намертво, а использование TTimer не обеспечивает нужную точность в 10мс.

З.ы. Использую C++ Builder XE
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
05.07.2016, 20:53
Ответы с готовыми решениями:

Отрисовка на Canvas "гладкой" наклонной линии
Если рисовать линию методом LineTo, то линия получается некрасивая, с видимой глазу зернистостью. А как нарисовать "гладкую"...

Отрисовка линии на canvas
Только начинаю работать с wpf. Мне нужно создать usercontrol линию на canvas. Рисую линию таким образом: Line MyLine =...

WPF canvas отрисовка точки
Здравствуйте уважаемые Форумчане. Может что то не правильно понимаю, так как многого не знаю. Объясните пожалуйста как в приложении...

23
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
05.07.2016, 21:14
Отрисовка из отдельного потока осуществляется с синхронизацией с основным потоком?
0
1 / 1 / 0
Регистрация: 24.02.2014
Сообщений: 45
05.07.2016, 22:23  [ТС]
d7d1c, да.

C++
1
2
3
4
5
6
7
8
    void __fastcall Execute(void)
    {
        while (!this->Terminated)
        {
            Sleep(10);
            this->Synchronize(&UpdateImg);
        }
    }
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
06.07.2016, 08:08
Честно сказать, не очень понятно ваше описание проблемы. Вы пишете, что есть таймер с точность 10 мс в отдельном потоке. Потом Вы пишете, что приходится добавлять задержку в 10 мс. В приведенном коде я вижу только одну задержку в 10 мс...
Вы пробовали для тестирования как-то упростить Ваш код? Например, выводить из потока какой-нибудь один элемент графики, а не "кучу другого динамического интерфейса"?
0
1 / 1 / 0
Регистрация: 24.02.2014
Сообщений: 45
06.07.2016, 09:20  [ТС]
d7d1c, в общем существует 3 потока. Это основной поток, поток для отрисовки и поток таймера. Таймер я реализовал следующим образом:

C++
1
2
3
4
5
6
7
8
if (!timerId) timerId = timeSetEvent(10, 0, TimerProc, 0, TIME_PERIODIC); //так создаётся таймер, который, как я понял, работает в своём отдельном потоке. Каждые 10мс он вызывает функцию TimerProc
 
//вот собсна та самая функция. Это просто инкремент глобальной переменной, которая хранит время
void CALLBACK TimerProc(UINT uTimerId, UINT uMessage, DWORD_PTR dwUser,
                              DWORD_PTR dw1, DWORD_PTR dw2)
{
    t++;
}
Да, я пробовал рисовать сначала простые элементы с помощью потока, и всё работало отлично. Но "заказчик" требует чтобы всё было сложно, быстро и красиво.

Мне вот что интересно. Даже если абстрагироваться именно от моей проблемы, как можно рисовать на канве сложные изображения (с множеством линий, прямоугольников, эллипсов и т.д.) с высокой скоростью (т.е. по факту при работе с таймером, что я привёл выше), и при этом чтобы программа могла успевать улавливать нужные значения таймера, и скажем, прекращать отрисовку каждые 5 секунд?
0
Модератор
 Аватар для vxg
3407 / 2178 / 354
Регистрация: 13.01.2012
Сообщений: 8,448
06.07.2016, 10:10
Rex_, зачем вам рисовать по таймеру? у вас какие-то "шевелящиеся" элементы интерфейса?
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
06.07.2016, 10:28
Цитата Сообщение от Rex_ Посмотреть сообщение
при этом чтобы программа могла успевать улавливать нужные значения таймера, и скажем, прекращать отрисовку каждые 5 секунд
Чтобы прекратить отрисовку максимально быстро в тот момент, когда об этом сигрализирует таймер, в функции, которая собственно и производит отрисовку, необходимо максимально часто проверять условие, что отрисовку необходимо прекратить
Каким образом Вы осуществляете остановку отрисовки. Выполняете для потока функцию Terminate?
1
1 / 1 / 0
Регистрация: 24.02.2014
Сообщений: 45
06.07.2016, 11:37  [ТС]
vxg, да, и их очень много. По сути, программа предназначена для моделирования физ. процессов в реальном времени.

d7d1c, да, Terminate естественно используется. Я тут задумался о том, как эффективно отлавливать нужные значения таймера и понял, что лучше это делать в самом таймере

C++
1
2
3
4
5
6
7
8
9
10
void CALLBACK TimerProc(UINT uTimerId, UINT uMessage, DWORD_PTR dwUser,
                              DWORD_PTR dw1, DWORD_PTR dw2)
{
    t++;
    if (Form1->RadioGroup1->ItemIndex==1 && (int)t%157==0 && t!=0)
    {
        timeKillEvent(timerId);
        timerId = NULL;
    }
}
Всем спасибо, тему можно закрыть
0
Модератор
 Аватар для vxg
3407 / 2178 / 354
Регистрация: 13.01.2012
Сообщений: 8,448
06.07.2016, 12:07
Rex_, возможно чем-то поможет https://www.cyberforum.ru/com-... ost9058429 там тоже есть поток который дергает перерисовку - правда он зависимый от событий но вы можете это поведение упразднить и просто вставить Sleep
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
06.07.2016, 12:55
Цитата Сообщение от Rex_ Посмотреть сообщение
что лучше это делать в самом таймере
Вы уверены, что из таймера можно вот так напрямую обращаться к Form1->RadioGroup1->ItemIndex? Ведь это отдельный поток. Думаю, нет нет, да и словите AV.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33374 / 21499 / 8235
Регистрация: 22.10.2011
Сообщений: 36,894
Записей в блоге: 11
06.07.2016, 13:00
Цитата Сообщение от d7d1c Посмотреть сообщение
Вы уверены, что из таймера можно вот так напрямую обращаться к Form1->RadioGroup1->ItemIndex?
Я уверен. Это не изменение состояния контрола, а операция чтения, никаких проблем не будет.
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
06.07.2016, 14:33
Цитата Сообщение от volvo Посмотреть сообщение
Я уверен. Это не изменение состояния контрола, а операция чтения, никаких проблем не будет.
Хм... А я думал, что из потока вообще под любым предлогом нельзя работать с VCL. Теперь выясняется, что можно... Ведь может получится так, что главный поток и мой поток одновременно обратятся к одному свойству. Почему же в случае чтения данных контрола моим потоком не возникнет AV?
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33374 / 21499 / 8235
Регистрация: 22.10.2011
Сообщений: 36,894
Записей в блоге: 11
06.07.2016, 14:41
Еще раз повторить? Потому что состояние компонента не изменится при чтении свойства. При этом компонент не перерисовывается, не лочит какие-то участки памяти. Ничего не делается, кроме чтения значения из памяти. Почему должен быть AV, можешь объяснить? Единственное, что может произойти плохого - так это чтение уже устаревшего значения через свойство, если в тот же момент времени, как ты будешь читать, кто-то другой возьмет и запишет туда (с синхронизацией, как положено) другое значение.
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
06.07.2016, 15:00
Сейчас уже не вспомню где, но когда читал про потоки, то было написано, что обращение к VCL компонентам из потока должно происходить через синхронизацию с основным потоком. Именно обращение, то есть и чтение и запись. Как было сказано, синхронизация необходима для того, чтобы к одной переменной одновременно не обратилось два потока.
Уважаемый volvo, тогда объясните, почему изменение значений свойств VCL из потока должно происходить через синхронизацию? Почему без нее возникает AV?
0
Модератор
 Аватар для vxg
3407 / 2178 / 354
Регистрация: 13.01.2012
Сообщений: 8,448
06.07.2016, 15:03
Цитата Сообщение от d7d1c Посмотреть сообщение
почему изменение значений свойств VCL из потока должно происходить через синхронизацию
наверное потому что эти изменения могут быть небезопасными при многопоточном выполнении - то есть к примеру во время изменения выделяется или удаляется память и если в это же самое время прочитать ее то... кстати в этой связи можно наверное сказать что не всякое чтение можно делать без синхронизации или я не прав, volvo?
0
управление сложностью
 Аватар для Почтальон
1693 / 1306 / 259
Регистрация: 22.03.2015
Сообщений: 7,545
Записей в блоге: 5
06.07.2016, 15:06
мне кажется потому что:
Цитата Сообщение от d7d1c Посмотреть сообщение
изменение значений свойств VCL
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
06.07.2016, 15:07
Цитата Сообщение от vxg Посмотреть сообщение
наверное потому что эти изменения могут быть небезопасными при многопоточном выполнении
В этом и вопрос: почему они не безопасны?
0
Модератор
 Аватар для vxg
3407 / 2178 / 354
Регистрация: 13.01.2012
Сообщений: 8,448
06.07.2016, 15:13
Цитата Сообщение от d7d1c Посмотреть сообщение
почему они не безопасны?
вроде же привел пример, но попробую еще раз. вот у нас есть список. мы хотим удалить элемент. для этого нужно удалить сам элемент и перенастроить ссылки предыдущего элемента на следующий. если это делают два потока одновременно и удаляемые элементы являются соседними то одному из потоков может посчастливится перенастроить ссылки в уже освобожденной памяти. точно так же и чтение - мы удалили элемент а кто то пытается его читать
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33374 / 21499 / 8235
Регистрация: 22.10.2011
Сообщений: 36,894
Записей в блоге: 11
06.07.2016, 15:22
Цитата Сообщение от d7d1c Посмотреть сообщение
Как было сказано, синхронизация необходима для того, чтобы к одной переменной одновременно не обратилось два потока.
А я про этот случай написал отдельно. И сказал, чем он чреват. Так называемый "read of inconsistent memory", чтение уже устаревшего значения. Но ни о каком AV тут речь не идет даже близко.

Цитата Сообщение от vxg Посмотреть сообщение
не всякое чтение можно делать без синхронизации
Ну, разумеется, если при чтении свойства происходит что-то более значительное, чем просто обращение по адресу в памяти, то лучше это делать с синхронизацией. Даже если и синхронизировать, ну посмотри: залочил ты объект, прочел значение из свойства, разлочил. И тут же другой поток-"писатель" взял и его изменил (имеет полное право, почему нет? Объект уже не залочен). А "читатель", радостный, что все сделал по правилам, идет и работает с уже устаревшими данными. И чего, помогла она, синхронизация? То же самое и без нее произойдет, только без мороки с Lock/Unlock (Enter/Leave, ну или как там еще методы называются? Их много теперь)
0
Модератор
 Аватар для vxg
3407 / 2178 / 354
Регистрация: 13.01.2012
Сообщений: 8,448
06.07.2016, 15:41
Цитата Сообщение от volvo Посмотреть сообщение
ну посмотри
то что значение может устареть пока оно движется от создателя к потребителю - этого никто не отменял и эту проблему невозможно решить по определению (разве только блокировкой создателя на время работы со значением).
я этот пример приводил как объяснение как можно поймать AV при чтении без синхронизации в ответ на
Цитата Сообщение от volvo Посмотреть сообщение
Ничего не делается, кроме чтения значения из памяти. Почему должен быть AV, можешь объяснить?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
06.07.2016, 15:41
Помогаю со студенческими работами здесь

Отрисовка сложных фигур на canvas
собственно вопрос, как из простых фигур, можно делать сложные? Когда я рисовал такие вот фигурки https://i.paste.pics/1PB0O.png все...

Отрисовка Планеты используя Canvas
Здравствуйте, есть такой код: function Planet (x,y, rad, n_sput, N:integer; k_orb, k_sput:real) // х, у - координаты планеты; rad -...

Отрисовка на Canvas при использовании MVVM
Проблема следующая: Есть список объектов, которые должны быть отражены в виде прямоугольников на холсте (Canvas). Места их отображения...

Canvas.TextOut отрисовка текста относительно центра
Доброго времени суток. Подскажите какое свойство Font нужно отредактировать, что бы текст отрисовывался относительно цента. По умолчанию...

Работа с timage.canvas, отрисовка нескольких картинок
Задача такая, есть белый фон, нужно отрисовать несколько картинок (всего 3), картинки примерно 10*10 пикселов, они будут заполнять канву...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а привычная функция main(). . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
Модель сукцессии микоризы
anaschu 24.01.2026
Решили писать научную статью с неким РОманом
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь(не выше 3-го порядка) постоянного тока с элементами R, L, C, k(ключ), U, E, J. Программа находит переходные токи и напряжения на элементах схемы классическим методом(1 и 2 з-ны. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru