title: Running several infinite loops with async/await
body: <p>I am developing android messanger app based on xamarin and .net 5 async/awaits.</p>
  
  <p>In my app i have producer/consumer pattern for processing messages which is made on infinite loops.</p>
  
  <p>for example ReadTcpClientAsync producer:</p>
  
  <pre><code>async Task ReadTcpClientAsync(CancellationToken cancellationToken)
  {
      cde.Signal();
      while (!cancellationToken.IsCancellationRequested)
      {
          byte[] buffer = await atc.ReadAsync(cancellationToken);
          // queue message...
      }
  }
  </code></pre>
  
  <p>or SendStatementsAsync consumer which deque messages and awaits WriteAsync</p>
  
  <pre><code>private async Task SendStatementsAsync(CancellationToken cancellationToken)
  {
      while (!cancellationToken.IsCancellationRequested)
      {
          var nextItem = await _outputStatements.Take();
          cancellationToken.ThrowIfCancellationRequested();
          // misc ...
          await atc.WriteAsync(call.Serialize());
      }
  }
  </code></pre>
  
  <p>and some consumers just await on Take calls</p>
  
  <pre><code> var update = await _inputUpdateStatements.Take();
  </code></pre>
  
  <p>this construction works pretty well on tests, but there is one method where i think i made a huge mistake.
  this method intent to run entire client backend, starting 3 pro/con while (true) loops simultaneously.</p>
  
  <p>here it is:</p>
  
  <pre><code>public async Task RunAsync()
  {
     _isRunning = true;
     _progress.ProgressChanged += progress_ProgressChanged;
      await InitMTProto(_scheme).ConfigureAwait(false); // init smth...
      // various init stuf...     
      await atc.ConnectAsync().ConfigureAwait(false); // open connection async
      // IS IT WRONG?
      try
      {                                   
          await Task.WhenAny(SendStatementsAsync(_cts.Token),
                                 ReadTcpClientAsync(_cts.Token),
                                 ProcessUpdateAsync(_cts.Token, _progress)).ConfigureAwait(false);
      }
      catch (OperationCanceledException oce)
      {   
  
      }
      catch (Exception ex)
      {
  
      }
  }
  </code></pre>
  
  <p>Forget about android for now, think any UI (WinForm, WPF, etc) OnCreate method in UI context to call RunAsync</p>
  
  <pre><code>protected async override void OnCreate(Bundle bundle)
  {
      // start RA 
      await client.RunAsync()
      // never gets here - BAD, but nonblock UI thread - good
      Debug.WriteLine("nevar");
  }
  </code></pre>
  
  <p>so, as you can see <strong>there is a problem</strong>. I can't do anything after RunAsync await call because it will never returns from Task.WhenAny(...). And i need perform status check there, but i need this pro/cons methods started, because my check wait on ManualResetEvent for it:</p>
  
  <pre><code>if (!cde.Wait(15000))
  {
      throw new TimeoutException("Init too long");
  }
  </code></pre>
  
  <p>Also, my check is async too, and it works like a charm :)</p>
  
  <pre><code>public async Task&lt;TLCombinatorInstance&gt; PerformRpcCall(string combinatorName, params object[] pars)
  {
      // wait for init on cde ...
      // prepare call ...
  
      // Produce
      ProduceOutput(call);
  
      // wait for answer
      return await _inputRpcAnswersStatements.Take();
  }
  </code></pre>
  
  <p>I think i should use another approach for starting this infinite loops, but i already have async Task methods all the way - so i really have no idea what to do.
  Any help please?</p>