Показаны сообщения с ярлыком поток. Показать все сообщения
Показаны сообщения с ярлыком поток. Показать все сообщения

пятница, 11 июня 2010 г.

Quartz-рисование в отдельном потоке

Будьте заранее готовы к некоторым проблемам, если захотите рисовать что-либо в отдельном потоке. Отдельный поток для рисования сложного контента необходим для того, чтобы GUI-контролы продолжали отвечать на ваши нежные прикосновения к экрану iPhone в то время, как на экране что-то продолжает рисоваться.

Из основного потока вы можете нажать какой-либо GUI-контрол (например кнопку или слайдер). Если нужно, то можно через изменение некоторых объектов (или даже простых bool переменных) попросить поток рисования изменить параметры рисунка или что-то в этом роде.

Есть одна очень существенная деталь, которую нужно помнить!

Ну само собой, нужно защищать переменные от одновременного изменения их значений из разных потоков одновременно. Для этого существуют различные средства синхронизации, pthread-мютексы (в C/C++), @synchronized-блоки (в Objective C).

Я хотел предупредить о другом. Сейчас я столкнулся с серьёзной проблемой. Оказывается, когда вы захотите сделать контекст (в который вы рисуете что-либо) текущим с помощью вызова функции UIGraphicsPushContext (и потом вернуть всё как было с помощью функции UIGraphicsPopContext) ТО ВАЖНО ЗНАТЬ, ЧТО ЭТИ 2 ФУНКЦИИ МОЖНО ВЫЗЫВАТЬ ТОЛЬКО ИЗ ОСНОВНОГО ПОТОКА ПРОГРАММЫ!

Мне нужно рисовать в контекст (не контекст экрана, а контекст в памяти) текст. Если я не сделаю этот контекст текущим, то текст в результате не нарисуется. Проблема в том, что я должен рисовать текст в отдельном потоке рисования. Из-за этого я вынужден из этого отдельного потока просить главный поток программы делать вызовы этих 2-х функций (UIGraphicsPushContext и UIGraphicsPopContext) и ждать каждый раз пока главный поток не соизволит это сделать (а главный поток может быть занят в это время чем-то важным, как ему кажется). Это приводит к целому ряду проблем, которых можно было бы избежать, если я бы знал об этом заранее (это бы позволило предпринять некоторые меры при предварительном проектировании, ещё до того, как была написана первая строка кода). У меня сейчас даже случаются дедлоки (взаимные блокировки потоков).

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

вторник, 27 апреля 2010 г.

Xcode — странные выходки отладчика

Отладчик, встроенный в Xcode, иногда вытворяет казалось бы необъяснимые вещи. Например, указатель согласно показаниям отладчика может быть равен нулю в том месте кода, где до этого была проверка, согласно которой в случае нулевого значения указателя код не должен дальше выполняться. Или бывает так, что строка приобретает зловещий вид через некоторое время после её инициализации (этот вид можно увидеть в Memory Browser).

Эти странные выходки Xcode-отладчика возникают по 2-м причинам, которые я успел уже выяснить:

1) Либо какая-то часть бинарного кода статической библиотеке не соответствует исходникам этой библиотеки (иначе говоря, исходники могли поменяться, а библиотеку забыли перекомпилировать).

2) Либо происходит обыкновенное переполнение стека. Тогда отладчик начинает показывать странные значения переменных. По крайней мере, на моей работе такое произошло в дополнительно созданном потоке. С помощью pthread-функций или с помощью класса NSThread можно изменять размер стэка потока перед его созданием потока, так как по умолчанию размер стека равен 512 килобайт. Благо, рядом со мной оказались опытные программисты. Они подсказали, что при переполнениях стека отладчик происходит повреждение данных, поэтому отладчик и показывает всякую чушь

Постоянные читатели