2016-09-22 8 views
1

Более новая версия C# имеет async/await. Но в Unity есть только yield. Как реализовать метод, в котором я могу использовать yield?Простой способ получения массива параллельно

Как и в случае с Promise.all([]) в Javascript, нам все равно, кто заканчивается первым, нам все равно, когда все будет сделано.

Чтобы представить больше контекста, представьте, что вы проектируете процедурный генератор рельефа, который генерирует в кусках; и вы уже настроили каждый кусок, чтобы генерировать с помощью ThreadPool, а затем предоставить API, который возвращает IEnumerator:

IEnumerator GenerateChunk() { 
    // procedural generation 
    // queue itself onto a ThreadPool 
    // when done, yield 
} 

IEnumerator GenerateChunks() { 
    for (int i = 0; i < chunks.Length; i++) { 
    yield return chunks[i].GenerateChunk(); 
    } 
} 

void GenerateMap() { 
    StartCoroutine(GenerateChunks()); 
} 

Можем ли мы сделать что-то вроде yield IEnumerator[]?

ОБНОВЛЕНИЕ: Я не уверен, что четко высказался. В основном я хочу сразу начать все GenerateChunk и позволить им закончить как можно быстрее, вместо того чтобы уступать один за другим.

Является ли мой код уже этим, или мне нужно что-нибудь еще?

+0

Правильный ответ может быть 'Enumerable.Concat()' http://stackoverflow.com/questions/1270024/nested-yield-return-with-ienumerable – bitinn

+0

** TL; DR: Игнорировать все выше, мой вопрос [лучше обобщен здесь] (http://forum.unity3d.com/threads/difference-between-yield-return-ienumerator-and-yield-return-startcoroutine.432571/). Прошу прощения за то, что я не понял этого.** – bitinn

ответ

1
yield return StartCoroutine(chunks[i].GenerateChunk()); 
+0

Это будет по-прежнему работать последовательно, я проверил его, чтобы быть уверенным. – bitinn

1

Я прочитал ваш вопрос, читать ответы и комментарии вы оставили, и я считаю, что вы не понять, как сопрограмму работы.

Coroutine не работает параллельно. Он будет запускать ваш код в порядке и в то же время, в том же Thread.

UPDATE: Я не уверен, что я выразился ясно. В принципе, я хочу сразу начать все GenerateChunk и позволить им закончить как можно быстрее, вместо того, чтобы уступать один за другим.

Является ли мой код уже этим, или мне нужно что-нибудь еще?

No. Если вы хотите называть эту функцию так быстро, как позицию, после каждой функции вы не должны yield. Каждый раз, когда вы yield, вас ждет один кадр. Я даже упоминал, что вы даже не вызываете функцию GenerateChunk? Посмотрите внимательно, вы это заметите. Функция GenerateChunk является сопроводительной функцией и должна называться StartCoroutine().

Do не выход после запуска GenerateChunk в петле для петли. Вы должны только выходить или прерываться вне функции цикла цикла. Вы можете выполнить простой тест производительности между вашим кодом и кодом ниже, чтобы подтвердить это с помощью Stopwatch.

IEnumerator GenerateChunk() 
{ 
    // procedural generation 
    // queue itself onto a ThreadPool 
    // when done, yield 
} 

IEnumerator GenerateChunks() 
{ 
    for (int i = 0; i < chunks.Length; i++) 
    { 
     StartCoroutine(GenerateChunk()); 
    } 
    yield break; 
    //Or yield return null; 
} 
+1

Просто, чтобы уточнить, я знаю, что они работают в одном потоке, и я знаю, как работает цепочка доходности. Параллельно я подразумеваю 'разрешение' в недетерминированном порядке. – bitinn

+0

Кроме того, 'GenerateChunk' возвращает' IEnumerator', я могу его уступить, он в конечном итоге перейдет в основную 'StartCoroutine' в' GenerateMap'. Я не думаю, что вам нужно снова обернуть его. – bitinn

+0

Хотя я не эксперт в Unity coroutine, я думаю, что если вы не вернете return StartCoroutine() ', он будет выполняться сам по себе, т.е. даже когда 'GenerateChunks' заканчивается, некоторые из' GenerateChunk() 'все еще могут работать. – bitinn

Смежные вопросы