D:\sideБлогПо запросу: Асинхронные действия (теория)

⚠️ Обращайте внимание на даты.
Этот блог больше не ведётся с 17 января 2023, и на тот момент с написания этой страницы (20.08.2013) прошло 9 лет.

Заголовок у несведущего читателя сразу вызовет вопросы о том, что такое “синхронные действия”. И если читатель знаком с программированием, то (скорее всего) вовсю этими действиями пользуется. Что такое “синхронные действия” проще объяснить, рассказав об асинхронных.

Начну с примера. Вы слышали о такой штуке, как JavaScript? Скорее всего, слышали. Представьте - когда загружается страница, с ней может загружаться огромное количество разнообразных файлов, а также выполняться тонна различных программ (скриптов). Предположим, что из-за этого страница загружается вполне ощутимое для пользователя время, но нормальное.

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

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

Что делать?

Ответ простой - вынести это очень долгое действие из общего потока программы. Так, чтобы оно выполнялось отдельно, не мешая общему течению. А это “общее течение” тем временем может проверять, не завершилось ли действие.

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

Раз уж я тут столько рассказываю о GameMaker Studio: там реализация этого приёма достаточно проста. Изолировать там можно всего несколько процессов: загрузку ресурсов и обращения к сети - они могут никак не взаимодействовать с игрой в процессе работы.

Когда вы совершаете одно из этих действий, GMS его запускает и продолжает работу. Но каждый шаг он проверяет, не закончилось ли оно. И если да - он запускает по всей игре событие “у нас асинхронка кончилась!”, причём соответствующего вида. По виду - определяется, какие данные получены в ходе выполненного задания. Это может быть статус (получилось или нет), сообщение (к интернету не подключены?) и сам результат (индекс ресурса или текст).

Эти данные хранятся в структуре данных map, о назначении, разновидностях и устройстве которой я расскажу в другой раз. Азы, которые вам нужно знать - map можно использовать, как словарь. Причём слова, в нём присутствующие, описаны в справке, а “определения словарных слов” - это нужные вам данные. Слова - ключи (key), а их “определения” - это значения (value). Применяя эти термины - в справке вы найдёте список ключей, соответствующих каждому событию.

Уж извините, но справку я раскапывать в этот раз не буду. GMS развивается настолько активно, что эти данные могут устареть, а я об этом и не узнаю - пост утонет.