# How to batch coroutines (IEnumerators) in parallel

We are working in a context where multithreading is not an option, so we're using coroutines to handle our loads. Often there are multiple things that need to be downloaded, leading to a pattern like this:

// set up multiple downloads

// handle each of the loads completed
{
// nasty and error prone way to check completion of all data

}


So I thought I would build a helper class to batch the downloads:

public BatchDownloader(
{
}
{
}
{
}


Used something like this:

public IEnumerator LoadAllTheThings()
{
{
};

}


Now that is much cleaner, more flexible, and it all works a treat, except that no load starts until the previous finishes. This obviously has a huge effect on load time. So in an attempt to have the coroutines run simultaneously, I'm trying the following:

public IEnumerator DownloadBatch()
{

{
}

{
yield return null;
{
{
}
}
}

}


Now while this correctly kicks off the coroutines, and runs them "in parallel", any code after the last yield in a coroutine is not executed. So in a method like the following:

private IEnumerator ReadDataCoroutine1()
{

}


DoPostDownloadStuff() is never called.

What am I misunderstanding here about stepping through these IEnumerators? Is there a way to do what I'm trying to, without introducing StartCoroutine into the batch downloader? (that is my solution for now, but idealy I'd like to not have to)

• Can you clarify why you want to avoid StartCoroutine? – DMGregory Apr 22 at 11:14
• @DMGregory because I want to be able to yield return the downloader IEnumerator out of another IEnumerator. Essentially this allows me to write code in a way very similar to async/await, where I can keep a series of related actions together. I can have a very high level object doing the StartCoroutine call – FlintZA Apr 22 at 13:04
• You can still do that with StartCoroutine. There's no restriction on calling StartCoroutine only once in the execution tree. – DMGregory Apr 22 at 13:07
• Sure, but I would need to pass the unity object down the chain to be used to call StartCoroutine (there is no reason for the batch class itself to be a unity object) – FlintZA Apr 22 at 13:27
• Sounds like you have a solution then. Does it differ from your desired behaviour in any way? – DMGregory Apr 22 at 13:36

For completeness sake, here is the version that uses a passed in MonoBehaviour to run the downloads.

: I've settled for this solution, I haven't had any success with a version that does not use StartCoroutine. [/Edit]

Note also the fix in ProcessDownload, for the case where no onDownloadComplete delegate was provided (whoops).

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace MB.Other
{
{

{
}

{

yield return null;