#ассинхронность #async #разбор_кода
Приветствую, друзья 👋
В рамках опроса про async метод, возник вопрос про асинхронность.
В данной публикации постараюсь развернуто ответить на заданный вопрос.
Поехали 🚀
Асинхронный код относится к стилю программирования, в котором задачи выполняются независимо друг от друга и не блокируют исполнение последующих инструкций до завершения.
Тогда как в традиционной синхронной модели программирования задачи выполняются последовательно: когда одна задача начинает выполнение, она блокирует выполнение других инструкций до завершения.
Если задача занимает много времени или ожидает ввода-вывода, мы можем столкнуться с замедлением работы программы.
Асинхронный код предлагает альтернативный подход: одна задача может выполняться параллельно с другими, что позволяет более эффективно использовать время процессора и других ресурсов
Вместо того, чтобы блокировать исполнение программы, асинхронный код передаст управление другим задачам и продолжит выполнение, когда ожидаемый результат будет доступен.
Асинхронный код часто используется там, где задачи, работающие в отдельных тредах, требуют ожидания результатов извне.
Например: выполнение сетевых запросов, чтение/запись файлов, обращение к базам данных и другие длительные операции ввода-вывода.
В языке программирования C# и фреймворке Unity асинхронное программирование можно реализовать с помощью ключевых слов async и await, а также с помощью использования корутин.
Эти механизмы позволяют реализовать асинхронный код более простым способом и повысить его читаемость, избегая явного управления потоками и блокировок.
В ходе дискуссии под опросом один из участников высказал предположение 👇:
Поясню, почему так сделать не получится.
UniTask - это обертка для того, чтобы можно было сделать кастомный await для типа.
UniTask не использует контекстов синхронизации и напрямую цепляется к PlayerLoop Unity.
Условия, при которых возможно применение await для типа:
- тип должен иметь public (или internal) метод GetAwaiter(), который должен вернуть тип ожидаемого объекта,
- ожидаемый объект должен реализовать интерфейс INotifyCompletion.
UniTask не содержит метод ConfigureAwait. ConfigureAwait содержит обычный Task и при его await можно сделать ConfigureAwait.
С UniTask достаточно сложно допустить ошибку с продолжением на разных потоках, так как после его await управление остается на главном потоке. В этом есть свои минусы, о которых я расскажу позже.
Что касается корутин.
Корутины в Unity - специальные функции, которые позволяют организовать асинхронное выполнение кода без использования множества потоков или сложных конструкций.
Корутины позволяют:
- делать паузы в выполнении кода,
- возвращать промежуточные результаты,
- выполнять итерации по определенным шагам.
Рассмотрим пример работы с корутинами в Unity 👇:
Продолжение в комментариях👇
Там же ждем ваши вопросы.
Всем хорошего дня👍
Приветствую, друзья 👋
В рамках опроса про async метод, возник вопрос про асинхронность.
В данной публикации постараюсь развернуто ответить на заданный вопрос.
Поехали 🚀
Асинхронный код относится к стилю программирования, в котором задачи выполняются независимо друг от друга и не блокируют исполнение последующих инструкций до завершения.
Тогда как в традиционной синхронной модели программирования задачи выполняются последовательно: когда одна задача начинает выполнение, она блокирует выполнение других инструкций до завершения.
Если задача занимает много времени или ожидает ввода-вывода, мы можем столкнуться с замедлением работы программы.
Асинхронный код предлагает альтернативный подход: одна задача может выполняться параллельно с другими, что позволяет более эффективно использовать время процессора и других ресурсов
Вместо того, чтобы блокировать исполнение программы, асинхронный код передаст управление другим задачам и продолжит выполнение, когда ожидаемый результат будет доступен.
Асинхронный код часто используется там, где задачи, работающие в отдельных тредах, требуют ожидания результатов извне.
Например: выполнение сетевых запросов, чтение/запись файлов, обращение к базам данных и другие длительные операции ввода-вывода.
В языке программирования C# и фреймворке Unity асинхронное программирование можно реализовать с помощью ключевых слов async и await, а также с помощью использования корутин.
Эти механизмы позволяют реализовать асинхронный код более простым способом и повысить его читаемость, избегая явного управления потоками и блокировок.
В ходе дискуссии под опросом один из участников высказал предположение 👇:
Где не найду описание, везде написано что поток может смениться после ожидания асинхронной операции.
Т.е. первая операция которая выполняется через await всё таки выполнится на главном потоке и только после этого может оказаться что код выполняется другим потоком?
...
//главный поток
await UniTask.WaitUntil(() => image.Source == icon).ConfigureAwait(false); //главный поток
//неизвестный поток(в том числе главный)
image.Source = icon; //возможна ошибка, если не главный поток
...
Поясню, почему так сделать не получится.
UniTask - это обертка для того, чтобы можно было сделать кастомный await для типа.
UniTask не использует контекстов синхронизации и напрямую цепляется к PlayerLoop Unity.
Условия, при которых возможно применение await для типа:
- тип должен иметь public (или internal) метод GetAwaiter(), который должен вернуть тип ожидаемого объекта,
- ожидаемый объект должен реализовать интерфейс INotifyCompletion.
UniTask не содержит метод ConfigureAwait. ConfigureAwait содержит обычный Task и при его await можно сделать ConfigureAwait.
С UniTask достаточно сложно допустить ошибку с продолжением на разных потоках, так как после его await управление остается на главном потоке. В этом есть свои минусы, о которых я расскажу позже.
Что касается корутин.
Корутины в Unity - специальные функции, которые позволяют организовать асинхронное выполнение кода без использования множества потоков или сложных конструкций.
Корутины позволяют:
- делать паузы в выполнении кода,
- возвращать промежуточные результаты,
- выполнять итерации по определенным шагам.
Рассмотрим пример работы с корутинами в Unity 👇:
Создадим новый скрипт и прикрепим его к объекту в сцене.
В созданном скрипте создадим функцию с ключевым словом IEnumerator. Это будет наша корутина.
IEnumerator MyCoroutine()
{
// Шаг 1
Debug.Log("Шаг 1");
yield return new WaitForSeconds(1f); // Пауза на 1 секунду
// Шаг 2
Debug.Log("Шаг 2");
yield return new WaitForSeconds(0.5f); // Пауза на 0.5 секунды
// Шаг 3
Debug.Log("Шаг 3");
yield return null; // Пауза на один кадр
// Шаг 4
Debug.Log("Шаг 4");
}
Вызовем корутину с помощью функции StartCoroutine в методе Start.
Продолжение в комментариях👇
Там же ждем ваши вопросы.
Всем хорошего дня👍
#опрос #async #gamedev
Итак, друзья )
Тестируем наш первый опрос в новом формате (спасибо за идею механики Алексею 😊)
Есть код, эммулирующий загрузку данных из сети 👇
❓Все ли в порядке с кодом? Или код требует улучшения❓
ГОЛОСОВАТЬ >>>
❗Внимание ❗Обсуждаем код и ведем дискуссию здесь, а в следующем посте Вы только голосуете и расписываете ответ в комментариях, если считаете, что код требует улучшений
Итак, друзья )
Тестируем наш первый опрос в новом формате (спасибо за идею механики Алексею 😊)
Есть код, эммулирующий загрузку данных из сети 👇
TimeSpan workDuration = TimeSpan.FromSeconds(10);
DateTime endDateTime = DateTime.Now.Add(workDuration);
while (DateTime.Now < endDateTime)
{
// some fast network operation, receive data from socket, speed 200 Mbps
Task receiveDataTask = Task.Delay(1);
//
await receiveDataTask;
}
❓Все ли в порядке с кодом? Или код требует улучшения❓
ГОЛОСОВАТЬ >>>
❗Внимание ❗Обсуждаем код и ведем дискуссию здесь, а в следующем посте Вы только голосуете и расписываете ответ в комментариях, если считаете, что код требует улучшений