Являются ли все методы в приложении iOS в одном потоке? (для предотвращения состояния гонки) - программирование
Подтвердить что ты не робот

Являются ли все методы в приложении iOS в одном потоке? (для предотвращения состояния гонки)

У нас может быть много обработчиков: touch handler, обработчик UIControl (кнопки, слайдеры), performSelector, CADisplayLink, события NSTimer, распознаватель жестов, обработчик акселерометра и блок завершения анимации UIView и некоторые другие.

Все ли они в одном потоке? То есть, только один из них может работать одновременно?

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

4b9b3361

Ответ 1

В общем, вы обнаружите, что большинство простых приложений на iOS, как правило, выполняют почти все действия в основном потоке. Как вы отметили, в тот момент, когда вы привносите многопоточность в изображение, вы добавляете еще один набор сложных проблем, о которых следует помнить. Многие разработчики не хотят беспокоиться об этой дополнительной сложности или не знакомы с GCD или потоками в целом, поэтому они избегают делать что-либо в фоновом потоке или очереди GCD.

Несколько элементов, которые вы перечисляете в своем вопросе, связаны с взаимодействием с UIKit, и в целом эти взаимодействия должны происходить в основном потоке (однако iOS 4.x добавила возможность выполнять некоторые функции рисования в фоновом режиме). Вы получаете касание и другие связанные события в основной теме. Если вы хотите обновить большинство аспектов интерфейса, безопасный способ сделать это - выполнить эти обновления в основном потоке.

Таймеры (NSTimer, CADisplayLink) могут обновлять свои обновления в фоновом потоке, присоединяя их к NSRunLoop, работающему в этом фоновом потоке. Вы редко видите, что люди это делают, но это можно сделать. Обычно люди настраивают таймеры в цикле основного запуска, что вызывает доставку обратных вызовов в основной поток.

При выполнении анимаций сами анимации будут запускаться в фоновом потоке (вы видите, что они не останавливаются, когда вы блокируете основной поток чем-то другим), но вы почти всегда получите блок завершения или обратный вызов на основной поток, когда они будут сделаны. Если я правильно помню, есть одно или два исключения, и они отмечены как таковые в документации Apple. Наличие этих обратных вызовов в основном потоке - это безопасный подход при работе с разработчиками, которые могут не понимать, что происходит за кулисами.

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

Люди пишут книги о лучших практиках при многопоточности кода, и вы можете найти много вопросов об этом здесь, поэтому я не буду вдаваться в подробности. Я могу вам сказать, что вы должны прочитать Apple Concurrency Руководство по программированию и посмотреть видео WWDC за последние два года, которые касаются Grand Central Dispatch. С GCD Apple значительно упростила добавление многопоточности в ваше приложение эффективным и (относительно) безопасным способом, и я рекомендую вам изучить это для своих приложений.

Например, у меня есть приложение с открытым исходным кодом для iOS, которое выполняет детальную визуализацию молекулярных структур. Я представляю каждый кадр на фоне GCD-очереди, потому что иногда они обрабатывают более 1/60-й секунды для обработки, и в этих случаях они могут вызвать отключение сенсорных событий, а интерфейс заикаться, если все это было в основном потоке, Кроме того, я видел повышение производительности на 40%, делая это при работе на более новых многоядерных устройствах. Чтобы избежать условий гонки, я обертываю взаимодействия с общими структурами данных и контекстами в очередях последовательной отправки, так что только одно действие может использовать ресурс за раз, независимо от того, какой поток работает конкретный блок. Это потребовало добавления нескольких строк кода, но преимущества производительности и удобства пользователя были огромными.