Coroutine loop

I’m trying to investigate behavior of Coroutine and found some strange thing, that i can not understand.

I want to create Coroutine loop, that runs 5 times and then exit. But my script stop after first iteration. First function of my loop does not run second time at all.

Can anybody explain me why this is so.

Here is full code.

public class TestCoroutine : MonoBehaviour {
  private enum CoroutineType { Coroutine_1, Coroutine_2 };

  private static TestCoroutine m_Self = null;
  private static float m_Delay = 0.5f;
  private static uint m_CounterMax = 5;
  private static uint m_Counter = 0;

  private static Dictionary<CoroutineType, IEnumerator> m_CoroutineDictionaty = new Dictionary<CoroutineType, IEnumerator> {
      { CoroutineType.Coroutine_1, Coroutine_1() },
      { CoroutineType.Coroutine_2, Coroutine_2() },
    };

  private void LoadCoroutine(CoroutineType _Value) {
    Debug.LogFormat("Loading: {0}", _Value);
    try {
      m_Self.StartCoroutine(m_CoroutineDictionaty[_Value]);
    } catch {
      Debug.LogErrorFormat("Can not found loading entry: {0}", _Value);
    }
  }

  private static IEnumerator Coroutine_1() {
    Debug.Log("Coroutine_1 - Pre yield");
    yield return new WaitForSeconds(m_Delay);
    Debug.Log("Coroutine_1 - start");
    ++m_Counter;
    Debug.LogFormat("m_Counter: {0}", m_Counter);
    m_Self.LoadCoroutine(CoroutineType.Coroutine_2);
    Debug.Log("Coroutine_1 - end");
  }

  private static IEnumerator Coroutine_2() {
    Debug.Log("Coroutine_2 - Pre yield");
    yield return new WaitForSeconds(m_Delay);
    Debug.Log("Coroutine_2 - start");
    Debug.LogFormat("m_Counter: {0}", m_Counter);
    if (m_Counter >= m_CounterMax) {
      Debug.Log("m_CounterMax reached");
      Debug.Log("Stop");
      yield break;
    } else {
      m_Self.LoadCoroutine(CoroutineType.Coroutine_1);
      Debug.Log("Coroutine_2 - end");
    }
  }

  private void Awake() {
    if (m_Self != null) {
      throw new InvalidProgramException(string.Format("Double Awake: {1}", this.name));
    }
    m_Self = this;
  }

  // Use this for initialization
  void Start() {
    Debug.Log("Start");
    this.LoadCoroutine(CoroutineType.Coroutine_1);
  }
}

Here is Console Output. Squares indicate which function print line.
93004-2017-04-28-13-21-53.png

I ask Unity Support.
This answer i received:

I have looked into your case. After talking with developers I have results. So your coroutine loop is a little bit incorrect. You are storing IEnumerator instances in your dictionary, but they cannot be reused. So solution to your problem would be storing delegates that can create IEnumerator instances ( they can be called freshly each time).

public class TestCoroutine : MonoBehaviour {
  private enum CoroutineType { Coroutine_1, Coroutine_2 };

  private static TestCoroutine m_Self = null;
  private static float m_Delay = 0.5f;
  private static uint m_CounterMax = 5;
  private static uint m_Counter = 0;

    private static Dictionary<CoroutineType, Func<IEnumerator>> m_CoroutineDictionaty = new Dictionary<CoroutineType, Func<IEnumerator>> {
      { CoroutineType.Coroutine_1, Coroutine_1 },
      { CoroutineType.Coroutine_2, Coroutine_2 },
    };

    private void LoadCoroutine(CoroutineType _Value)
    {
        Debug.LogFormat("Loading: {0}", _Value);

        try
        {
            m_Self.StartCoroutine(m_CoroutineDictionaty[_Value]());
        }
        catch
        {
            Debug.LogErrorFormat("Can not found loading entry: {0}", _Value);
        }
    }

    private static IEnumerator Coroutine_1() {
    Debug.Log("Coroutine_1 - Pre yield");
    yield return new WaitForSeconds(m_Delay);
    Debug.Log("Coroutine_1 - start");
    ++m_Counter;
    Debug.LogFormat("m_Counter: {0}", m_Counter);
    m_Self.LoadCoroutine(CoroutineType.Coroutine_2);
    Debug.Log("Coroutine_1 - end");
  }

  private static IEnumerator Coroutine_2() {
    Debug.Log("Coroutine_2 - Pre yield");
    yield return new WaitForSeconds(m_Delay);
    Debug.Log("Coroutine_2 - start");
    Debug.LogFormat("m_Counter: {0}", m_Counter);
    if (m_Counter >= m_CounterMax) {
      Debug.Log("m_CounterMax reached");
      Debug.Log("Stop");
      yield break;
    } else {
      m_Self.LoadCoroutine(CoroutineType.Coroutine_1);
      Debug.Log("Coroutine_2 - end");
    }
  }

  private void Awake() {
    if (m_Self != null) {
      throw new InvalidProgramException(string.Format("Double Awake: {1}", this.name));
    }
    m_Self = this;
  }

  // Use this for initialization
  void Start() {
    Debug.Log("Start");
    m_Self.LoadCoroutine(CoroutineType.Coroutine_1);
  }
}