Форум: "WinAPI";
Текущий архив: 2008.10.12;
Скачать: [xml.tar.bz2];
ВнизЗависает API функция EnterCriticalSection Найти похожие ветки
← →
Unknown user © (2007-12-12 17:37) [0]Рисую из созданного мной потока на канве и почему-то периодически программа зависает. Более подробные поиски выявили, что зависает программа при вызове TPen.Assign при входе в критическую секцию.
Не гарантирую, что код отвечающий за отрисовку потокобезопасный, слишком он сложен и запутан.
Что посоветуете?
← →
Eraser © (2007-12-12 17:43) [1]
> Unknown user © (12.12.07 17:37)
перед прорисовкой на канвасе нужно вызывать Canvas.Lock, после отрисовки - Canvas.Unlock. И это еще не обезопасит полностью от проблем с потокобезопасностью..
по-хорошему надо перехватывать сообщение WM_SYSCOLORCHANGE.
← →
Unknown user © (2007-12-12 18:14) [2]> Eraser
да, я блокирую канвас от доступа к нему из других потоков. можно подробнее о том как делать "по-хорошему"?
← →
Unknown user © (2007-12-13 10:12) [3]А может можно обойтись без рисования в отдельном потоке? Задача такая: рисование происходит в основном и дополнительном окне. Рисование в основном окне должно иметь больший приоритет, то есть при необходимости перерисовки в основном окне рисование в дополнительном должно приостанавливаться или прекращаться. Как это можно реализовать?
← →
Сергей М. © (2007-12-13 10:20) [4]
> может можно обойтись без рисования в отдельном потоке?
Не только можно обойтись, но и нельзя этого делать вообще.
Рисовать на канве виз.контрола в VCL-приложении имеет право и обязан основной поток, задача же дополнительного сводится к подготовке данных для рисования, а не к собственно рисованию.
← →
tesseract © (2007-12-13 10:24) [5]
> задача же дополнительного сводится к подготовке данных для
> рисования, а не к собственно рисованию.
Дополню : В доп потоке созаеться область для BitBlt, передаеться в основной поток, где она уже просто вставляеться в область. "На пальцах", примерно, как в DoubleBuffered у формы - сначала готовиться картинка, а в onpiant вклеиваем.
← →
ыы (2007-12-13 10:42) [6]
> по-хорошему надо перехватывать сообщение WM_SYSCOLORCHANGE
А это к чему? Или это надо понимать как "дополнительно к рисованию на канве ещё надо..."?
← →
Unknown user © (2007-12-13 10:44) [7]> Сергей М. & tesseract
Основной поток рисует на канве визуального контрола, вторичный поток рисует в памяти на канве битмапа, после окончания рисования с использованием Synchronize копирует битмап в канвас другого визуального контрола.
Как можно прерывать рисование в дополнительном окне? Насколько я понимаю использование Application.ProcessMessages внутри процедуры рисования чревато непредсказуемым поведением?
← →
Unknown user © (2007-12-13 10:46) [8]
> Как можно прерывать рисование в дополнительном окне?
Я имел ввиду без использования дополнительных потоков.
← →
Eraser © (2007-12-13 10:54) [9]
> Unknown user © (13.12.07 10:44) [7]
> после окончания рисования с использованием Synchronize копирует
> битмап в канвас другого визуального контрола.
странная методика.. по-моему нужно использовать InvalidateRect, а в OnPaint прорисовывать.
← →
ыы (2007-12-13 10:58) [10]Eraser, ответь на [6] плз!
← →
Eraser © (2007-12-13 11:03) [11]
> ыы (13.12.07 10:42) [6]
а ты посмотри код функции обработчика WM_SYSCOLORCHANGE в TWinControl по-моему (у меня просто Делфи нет под рукой), сразу все понятно станет, очень непотокобезопасная штука )
← →
Unknown user © (2007-12-13 11:03) [12]
> странная методика.. по-моему нужно использовать InvalidateRect,
> а в OnPaint прорисовывать.
Так в OnPaint и прорисовывается. Ладно, наверно я недостаточно ясно выражаюсь, распишу поэтапно:
1. В окно визуального контрола основного окна приходит сообщние WM_PAINT
2. Вызывается процедура OnPaint которая после отрисовки в основном окне вызывает процедуру рисования в дополнительном окне (отображается не одна и та же информация).
3. Рисование в дополнительном окне реализовано в отдельном потоке, рисование просиходит не напрямую в канвас виз. контрола а через битмап.
4. Рисование в основном окне имеет приоритет (не должно быть подтормаживаний).
Так реализовано сейчас. Насколько я понимаю, зависание проги происходит в процессе рисования в дополнительном окне, когда в основном тоже начинается рисование.
← →
Сергей М. © (2007-12-13 11:09) [13]
> вторичный поток рисует в памяти на канве битмапа
А нафиг тогда крит.секция, если фигурирует Synchronize ?
Ты же все равно после формирования битмапа передаешь его в осн.поток, который собссно и отрисовывает готовый битмап на канве виз.контрола.
Т.е. у тебя к канве битмапа в каждый момент времени обращается только один поток, что не требует никакой синхронизации.
← →
Eraser © (2007-12-13 11:12) [14]
> Unknown user © (13.12.07 11:03) [12]
> которая после отрисовки в основном окне вызывает процедуру
> рисования в дополнительном окне
каким образом это происходит?
и каким образом осуществляется прорисовка в доп. окне.. есть Synchronize"ы?
по-моему все слегка усложнено )
← →
Unknown user © (2007-12-13 12:34) [15]
> А нафиг тогда крит.секция, если фигурирует Synchronize
> ?
>
> Ты же все равно после формирования битмапа передаешь его
> в осн.поток, который собссно и отрисовывает готовый битмап
> на канве виз.контрола.
>
> Т.е. у тебя к канве битмапа в каждый момент времени обращается
> только один поток, что не требует никакой синхронизации.
>
Критическая секция вызывается неявно в процедуре рисования (посмотрите к примеру VCL код TPen.Assign)
Synchronize использую только при копировании уже отрисованного в битмапе изображения на канвас контрола.
Synchronize(Draw);
Procedure TMapDrawThread.Draw;
begin
Canvas.Draw(0,0,BMP);
end;
> каким образом это происходит?
Да просто все происходит
procedure T.OnPaint
.
.
нарисовали, вызываем рисование во втором окне
SecondDraw
end;
> по-моему все слегка усложнено )
Жду предложений по упрощению.
← →
Сергей М. © (2007-12-13 12:41) [16]
> Procedure TMapDrawThread.Draw;
> begin
> Canvas.Draw(0,0,BMP);
> end;
>
Метод канвы какого объекта ты здесь вызываешь ?
Из кода это неочевидно ..
← →
Unknown user © (2007-12-13 12:53) [17]
> Метод канвы какого объекта ты здесь вызываешь ?
канва визуального контрола в дополнительном окне.
← →
Eraser © (2007-12-13 13:17) [18]
> Unknown user © (13.12.07 12:53) [17]
> Procedure TMapDrawThread.Draw;begin Canvas.Draw(0,0,BMP);
> end;
убрать в OnPaint второго окна. зачем себе жизнь усложнять то? Такой механизм прорисовки (через WM_PAINT) придуман не просто так.
← →
Сергей М. © (2007-12-13 13:23) [19]
> канва визуального контрола в дополнительном окне
Canvas - это имя поля класса TMapDrawThread ?
Если да, то где и как оно инициализируется в созданном тобой объекте класса TMapDrawThread ?
← →
DiamondShark © (2007-12-13 13:26) [20]
> Жду предложений по упрощению.
Убери из OnPaint одного контрола вызов прорисовки второго контрола.
OnPaint должен рисовать только то, что относится к себе.
Картинку для рисования можешь готовить как угодно, в том числе и в отдельном потоке. Когда кадр для прорисовки готов, отдавай контролу картинку и вызывай Invalidate.
Пусть WM_PAINT приходит тогда, когда решит нужным система. Не насилуй технику.
← →
tesseract © (2007-12-13 16:36) [21]
> Картинку для рисования можешь готовить как угодно, в том
> числе и в отдельном потоке. Когда кадр для прорисовки готов,
> отдавай контролу картинку и вызывай Invalidate.
А я что предлагал ?
> Пусть WM_PAINT приходит тогда, когда решит нужным система.
> Не насилуй технику.
Его контролу просто послать можно. Или вызвать Refresh/Repaint.
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2008.10.12;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.042 c