title: Asynchronous behaviour for NPC in C# game
body: <p><strong>This question is related to <a href="https://stackoverflow.com/questions/14952689/using-c-sharp-5-async-to-wait-for-something-that-executes-over-a-number-of-game">this one (Using C# 5 async to wait for something that executes over a number of game frames)</a>.</strong></p>
  
  <h2>Context</h2>
  
  <p>When Miguel de Icaza first presented C# 5 async framework for games at <a href="http://tirania.org/slides/AltDevConf-2012-Mono.pdf" rel="nofollow noreferrer">Alt-Dev-Conf 2012</a>, I really loved the idea of using <code>async</code> and <code>await</code> to handle "scripts" (so to speak, because they are in c#, and in my case, compiled---just in time but compiled anyway) in games.</p>
  
  <p>Upcoming <a href="http://paradox3d.net" rel="nofollow noreferrer">Paradox3D</a> game engine seems to <a href="http://paradox3d.net/features/scripting.html#microthreading" rel="nofollow noreferrer">rely on the async framework</a> to handle scripts too, but from my point of view, there is a real gap between the idea and the implementation.</p>
  
  <p>In the <a href="https://stackoverflow.com/questions/14952689/using-c-sharp-5-async-to-wait-for-something-that-executes-over-a-number-of-game">linked related question</a>, someone uses <code>await</code> to make a NPC perform a sequence of instructions while the rest of the game is still running.</p>
  
  <h2>Idea</h2>
  
  <p>I want to go a step further and allow a NPC to perform several actions at the same time, while expressing those actions in a sequential manner.
  Something along the lines of:</p>
  
  <pre><code>class NonPlayableCharacter 
  {
      void Perform()
      {
          Task walking = Walk(destination); // Start walking
          Task sleeping = FallAsleep(1000); // Start sleeping but still walks
          Task speaking = Speak("I'm a sleepwalker"); // Start speaking
          await walking; // Wait till we stop moving.
          await sleeping; // Wait till we wake up.
          await speaking; // Wait till silence falls
      }
  }
  </code></pre>
  
  <p>To do so, I used Jon Skeet's as-wonderful-as-ever <a href="https://stackoverflow.com/a/14954656/1614219">answer</a> from the <a href="https://stackoverflow.com/questions/14952689/using-c-sharp-5-async-to-wait-for-something-that-executes-over-a-number-of-game">related question</a>.</p>
  
  <h2>Implementation</h2>
  
  <p>My toy implementation consists of two files, NPC.cs and Game.cs
  NPC.cs:</p>
  
  <pre><code>using System;
  using System.Threading.Tasks;
  
  namespace asyncFramework
  {
      public class NPC
      {
          public NPC (int id)
          {
              this.id = id;
  
          }
  
          public async void Perform ()
          {
                      Task babbling = Speak("I have a superpower...");
              await Speak ("\t\t\t...I can talk while talking!");
              await babbling; 
              done = true;
          }
  
          public bool Done { get { return done; } }
  
          protected async Task Speak (string message)
          {
              int previousLetters = 0;
              double letters = 0.0;
              while (letters &lt; message.Length) {
                  double ellapsedTime = await Game.Frame;
                  letters += ellapsedTime * LETTERS_PER_MILLISECOND;
                  if (letters - previousLetters &gt; 1.0) {
                      System.Console.Out.WriteLine ("[" + this.id.ToString () + "]" + message.Substring (0, (int)Math.Floor (Math.Min (letters, message.Length))));
                      previousLetters = (int)Math.Floor (letters);
                  }
              }
          }
  
          private int id;
          private bool done = false;
          private readonly double LETTERS_PER_MILLISECOND = 0.002 * Game.Rand.Next(1, 10);
      }
  }
  </code></pre>
  
  <p>Game.cs:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Threading.Tasks;
  
  namespace asyncFramework
  {
      class Game
      {
          static public Random Rand { 
              get { return rand; }
          }
  
          static public Task&lt;double&gt; Frame {
              get { return frame.Task; }
          }
  
          public static void Update (double ellapsedTime)
          {
              TaskCompletionSource&lt;double&gt; previousFrame = frame; // save the previous "frame"
              frame = new TaskCompletionSource&lt;double&gt; (); // create the new one
              previousFrame.SetResult (ellapsedTime); // consume the old one
          }
  
          public static void Main (string[] args)
          {
              int NPC_NUMBER = 10; // number of NPCs 10 is ok, 10000 is ko
              DateTime currentTime = DateTime.Now; // Measure current time
              List&lt;NPC&gt; npcs = new List&lt;NPC&gt; (); // our list of npcs
              for (int i = 0; i &lt; NPC_NUMBER; ++i) { 
                  NPC npc = new NPC (i); // a new npc
                  npcs.Add (npc); 
                  npc.Perform (); // trigger the npc actions
              }
              while (true) { // main loop
                  DateTime oldTime = currentTime;
                  currentTime = DateTime.Now;
                  double ellapsedMilliseconds = currentTime.Subtract(oldTime).TotalMilliseconds; // compute ellapsedmilliseconds
                  bool allDone = true;
                  Game.Update (ellapsedMilliseconds); // generate a new frame
                  for (int i = 0; i &lt; NPC_NUMBER; ++i) {
                      allDone &amp;= npcs [i].Done; // if one NPC is not done, allDone is false
                  }
                  if (allDone) // leave the main loop when all are done.
                      break;
              }
              System.Console.Out.WriteLine ("That's all folks!"); // show after main loop
          }
  
          private static TaskCompletionSource&lt;double&gt; frame = new TaskCompletionSource&lt;double&gt; ();
          private static Random rand = new Random ();
      }
  }
  </code></pre>
  
  <p>This is quite a straightforward implementation!</p>
  
  <h2>Problem</h2>
  
  <p>However, it doesn't seem to work as expected.</p>
  
  <p>More precisely, with NPC_NUMBER at 10, 100 or 1000, I have no problem. But at 10,000 or above, the program doesn't complete anymore, it write "speaking" lines for a while, then nothing more gets on Console.
  While I'm not thinking of having 10,000 NPCs in my game at once, they also won't writeline silly dialogs, but also move, animate, load textures and so on. So I'd like to know what is wrong with my implementation and if I have any chance of fixing it.</p>
  
  <p>I must precise that the code is running under Mono. Also, the "problematic" value could be different at your place, it can be a computer specific thing. If the problem can't seem to be reproduced under .Net, I will try it under Windows.</p>
  
  <h2>EDIT</h2>
  
  <p>In .Net, it runs up to 1000000, although it requires time to initialise, it may be a Mono specific problem.
  Debugguer data tell me that there are indeed NPCs that aren't done. No info as to why yet, sadly.</p>
  
  <h2>EDIT 2</h2>
  
  <p>Under Monodevelop, launching the application without a debugger seems to correct the problem. No idea as to why however...</p>
  
  <h2>End word</h2>
  
  <p>I realise this is a really, really lengthy question, and I hope you will take the time to read it, I'd really like to understand what I did wrong. </p>
  
  <p>Thank you very much in advance.</p>