title: Task chaining in Firebase Unity, how to avoid code pyramid?
body: <p>Supposed I have to get login information from the server then login, then after the login do something next. The goal is to encapsulate all of this into something that caller can wait.</p>
  
  <p>However each of Firebase C# API call already returned separate tasks (that has already been started). My approach is to think of how to chain each of these separate task together.</p>
  
  <p>I am thinking of making a new <code>Task</code> that represent this since it also seems great for aggregating all the exceptions for the caller to catch.</p>
  
  <p>We have</p>
  
  <p><code>Task&lt;DataSnapshot&gt; getKeyTask  = Database.Child("keyLocation").GetValueAsync();
  </code></p>
  
  <p><code>GetValueAsync</code> as I understand already spun up the task. We can observe the returned task or better use continuation to begin something when it finished.</p>
  
  <p><code>Task loginTask = Auth.SignInWithEmailAndPasswordAsync(username, password);
  </code></p>
  
  <p><code>Auth.SignInWithEmailAndPasswordAsync</code> also spun up a <strong>new</strong> task in itself. I can also use continuation to wait and begin something else.</p>
  
  <p>After the login I would like to use another database call to get user data.</p>
  
  <p>So</p>
  
  <pre><code>public Task Login()
  {
      Task&lt;DataSnapshot&gt; getKeyTask = Database.Child("keyLocation").GetValueAsync();
  
      Task loginAfterGetKeyTask = getKeyTask.ContinueWith(gkt =&gt;
      {
          Task loginTask = Auth.SignInWithEmailAndPasswordAsync(gkt.Result.___.username, gkt.Result.____.password);
          loginTask.ContinueWith(lt =&gt; { ....the next task.... });
      });
  
      return loginAfterGetKeyTask;
  }
  </code></pre>
  
  <p>There are 2 problems I found : </p>
  
  <ol>
  <li>As it goes on the code is getting deeper in the pyramid. Is there any way I can do to make the code looks more sequential?</li>
  <li>This <code>Login()</code> function I want to return a <code>Task</code> so that caller can wait for the whole login process to finish then continue, etc. But currently the returned <code>loginAfterGetKey</code> task finished even if there are more things to do inside. I could keep doing <code>.ContinueWith</code> chaining on the outside if not for that there are one more Firebase task that is executed. Ideally I would like to return the <code>Task</code> that represent the whole thing but they are nested inside. Firebase's method start those task on it's own so I think I could not try to bundle all the task on my own.</li>
  </ol>
  
  <p>I tried encapsulate all the tasks as a new Task start from <code>Task.Factory.StartNew</code> however "GetComponent can only be called from main thread" is a problem. (The <code>Auth</code> and other Firebase service would require <code>GetComponent</code>)</p>
  
  <p>I tried using <code>IEnumerator</code> as a return of <code>Login()</code> and planned to put <code>yield</code> in this function, however, "The yield statement cannot be used inside anonymous method or lambda expression".</p>
  
  <p>I tried using <code>loginTask.Wait()</code> inside the first <code>ContinueWith</code> in order to make <code>loginAfterGetKeyTask</code> that I return from this function not arrive at <code>IsCompleted</code> state until it reacehs the end (which would have to wait for the tasks inside) but since the lambda in this <code>ContinueWith</code> is in the main thread, it causes deadlock.</p>