Only one coroutine can wait for another coroutine

Hello guys!

I found that only one coroutine can wait for another coroutine! This behavior is very rare, since coroutines are a simulation for threads, and there are many cases in which you would like to wait for another ongoing operation (like semaphores in threads).

I also send a bug report to Unity, but haven’t receive any response for a long time (about one moth from current date!)

Steps to reproduce:

  1. Start a coroutine and obtain the Coroutine object.
  2. Start a second coroutine, pass the first coroutine as a parameter and wait for it using yield.
  3. Start a third coroutine, pass the first coroutine as a parameter and wait for it using yield.
  4. The third coroutine never gets to end.

You will receive a message saying:
“Another coroutine is already waiting for this coroutine!
Currently only one coroutine can wait for another coroutine!”

PS: You can also add the attached script code to a GameObject and press play.

using UnityEngine;
using System.Collections;

public class CoroutineTest : MonoBehaviour
{
	void Start () {
		Debug.Log ("start");
		StartCoroutine(startFunction());
		Debug.Log ("end");
	}
	
	IEnumerator startFunction ()
	{
		Debug.Log ("begin start function");
		Coroutine f1 = StartCoroutine(function1 ());
		StartCoroutine(wait_function1 (f1));
		StartCoroutine(wait_function2 (f1));
		Debug.Log ("end start function");

		yield break;
	}

	IEnumerator function1()
	{
		Debug.Log ("begin function 1");
		yield return new WaitForSeconds(3);
		Debug.Log ("end function 1");
	}

	IEnumerator wait_function1(Coroutine c)
	{
		Debug.Log ("begin function 2");
		yield return c;
		Debug.Log ("end function 2");
	}

	IEnumerator wait_function2(Coroutine c)
	{
		Debug.Log ("begin function 3");
		yield return c;
		Debug.Log ("end function 3");
	}
}

Script that shows the behaviour:

void Start() {

    var coroutine1 = StartCoroutine(CR1());

    var coroutine2 = StartCoroutine(CR2(coroutine1));

    var coroutine3 = StartCoroutine(CR2(coroutine1));
}

IEnumerator CR1() {
    yield return new WaitForSeconds(10f);
}

IEnumerator CR2(Coroutine CR) {
    yield return CR;
    Debug.Log("CR2 FINISHED!");
}

As there’s a meaningfull error message, this is not a bug, but a feature.

You’ll simply have to get around this in some other way. Having a bool flag the first coroutine sets to true when it’s done, and having the other coroutines wait for that flag is the quickest and dirtiest way to do this.

Ohh, nice, they finally added a message ^^. In the past we had coroutines to get stuck forever. A bug is when something is stated to work a certain way but somehow it doesn’t. Since they never said that is it possible it’s not a bug but maybe a missing feature.

I’ve written the CoroutineHelper class on the wiki which allows you to run a coroutine seperated from your actual object (it uses a lazy-initialized singleton object). It also allows you to wait for a “Run” instance multiple times by simply creating a “wait coroutine” for each case.