Как использовать async/await?

Программирование на Юнити.

Как использовать async/await?

Сообщение Инженер 28 май 2020, 15:31

Простите за тупость, но я не могу найти понятных примеров для "чайников". Например, мне нужно создать 10000 объектов асинхронно. Как это сделать? Из этой инструкции я понял, что куда-то надо впихнуть метод расширения GetAwaiter, который возвращает объект Awaiter, но вопрос- куда? Я расстроен необходимостью вставлять какие-то вызовы, изначально я думал, что можно вообще любой код заставить работать асинхронно, тупо подставив async вместо void, но по ходу я жестоко ошибался. Можете на пальцах объяснить?

Синтаксис:
Используется csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading.Tasks;

public class AsyncAwaitTask : MonoBehaviour
{
    public GameObject go;
    public List<GameObject> gos = new List<GameObject>();

    async void Update()
    {
        await AsyncMethod();
    }

    int cycles = 10000;
    async Task AsyncMethod()
    {
        for (int i = 0; i < cycles; i++)
        {
            Vector3 pos = new Vector3(Random.Range(0, 100), 2f, Random.Range(0, 100));
            GameObject obj = Instantiate(go, pos, Quaternion.identity);
            gos.Add(obj);
        }
    }
}
 


Изначально хотел потоки изучить, но так такая жесть, нельзя использовать api Unity вне главного потока! У меня нет тяжелых вычислений, которые можно было бы изолировать вне основного потока. Самое тяжелое связано с getPosition/setPosition, setActive и пр- как раз то, что не работает из сторонних потоков. Я подумал, ну их на фиг, эту мультипоточность, буду асинхронные штуки изучать. В await'ах вызовы Unity api вроде должны работать.
Инженер
UNIт
 
Сообщения: 88
Зарегистрирован: 22 май 2016, 11:13

Re: Как использовать async/await?

Сообщение Jarico 28 май 2020, 16:35

IEnumerator используй

Он выполняет код параллельно с главным потоком
Github: _https://github.com/redheadgektor
Discord: Конь! Чаю!#9382 (сижу редко)
YouTube: _https://www.youtube.com/channel/UCPQ04Xpbbw2uGc1gsZtO3HQ
Telegram: _https://t.me/redheadgektor
Аватара пользователя
Jarico
Адепт
 
Сообщения: 1084
Зарегистрирован: 06 янв 2019, 17:37
Откуда: 0xDEAD
Skype: none
  • Сайт

Re: Как использовать async/await?

Сообщение 1max1 28 май 2020, 17:07

Если уже потоки юзать в юнити, то лучше jobs system использовать. Впрочем, для того и придумано.
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: Как использовать async/await?

Сообщение seaman 28 май 2020, 18:52

IEnumerator используй

Он выполняет код параллельно с главным потоком

Это неверно. Он выполняет код в главном потоке.
seaman
Адепт
 
Сообщения: 8352
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара

Re: Как использовать async/await?

Сообщение Инженер 28 май 2020, 19:16

Jarico писал(а):IEnumerator используй


IEnumerator нельзя выполнять в классах, не унаследованных от MonoBehaviour. Это для меня минус. А async/await можно в любом классе делать.

1max1 писал(а):Если уже потоки юзать в юнити, то лучше jobs system использовать. Впрочем, для того и придумано.


Jobs разве можно использовать без ECS system?

===========

Нашел рабочий вариант:

Синтаксис:
Используется csharp

    async void Blablabla()
    {
        await Task.Run(() =>
        {
            //любой код
        }
        );
    }


Но проблема та же, что и с мультипоточностью. Нельзя пользоваться api Unity. Например, нижеследующий метод не получится использовать, т.к. Random.Range и Instantiate должны юзаться в main thread.

А как же обойти это ограничение? Я слышал про обратные вызовы в main thread. Что за зверь? Это может помочь?

Синтаксис:
Используется csharp
    public GameObject go;
    int cycles = 10000;
    public List<GameObject> gos = new List<GameObject>();

    async void Alalala()
    {
        await Task.Run(() =>
        {
            for (int i = 0; i < cycles; i++)
            {
                gos.Add(spawnGO());
            }
        }
        );
    }

    GameObject spawnGO()
    {
        Vector3 pos = new Vector3(Random.Range(0, 100), Random.Range(0, 100), Random.Range(0, 100));
        return Instantiate(go, pos, Quaternion.identity);
    }
Инженер
UNIт
 
Сообщения: 88
Зарегистрирован: 22 май 2016, 11:13

Re: Как использовать async/await?

Сообщение waruiyume 28 май 2020, 19:21

Jobs разве можно использовать без ECS system?

Можно. Jobs выполняются в том же кадре в котором добавлены в очередь, т.ч. оно вам не надо.
Аватара пользователя
waruiyume
Адепт
 
Сообщения: 6143
Зарегистрирован: 30 окт 2010, 05:03
Откуда: Ростов на Дону

Re: Как использовать async/await?

Сообщение seaman 28 май 2020, 19:34

IEnumerator нельзя выполнять в классах, не унаследованных от MonoBehaviour.

Можно. В MEC, например это реализовано.
seaman
Адепт
 
Сообщения: 8352
Зарегистрирован: 24 янв 2011, 12:32
Откуда: Самара

Re: Как использовать async/await?

Сообщение tchezarre 19 янв 2021, 17:08

Синтаксис:
Используется csharp
/// <summary>
/// Тривиальный менеджер задачек
/// </summary>
public static class MiniTask
{
    public static async void Run(float delaySec, System.Action action)
    {
        var tm = Time.time + delaySec;
        while (tm > Time.time)
        {
            await Task.Yield();
        }
        try
        {
            action();
        }
        catch (System.Exception e)
        {
            Debug.LogError(e);
        }
    }
}

.....
   MiniTask.Run(0.25f, ()=>{ /* Юнити вызовы*/});
 
tchezarre
UNец
 
Сообщения: 25
Зарегистрирован: 23 янв 2014, 06:44
Откуда: Владивосток


Вернуться в Скрипты

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 10