title: C# async within an action
body: <p>I would like to write a method which accept several parameters, including an action and a retry amount and invoke it.</p>
  
  <p>So I have this code:</p>
  
  <pre><code>public static IEnumerable&lt;Task&gt; RunWithRetries&lt;T&gt;(List&lt;T&gt; source, int threads, Func&lt;T, Task&lt;bool&gt;&gt; action, int retries, string method)
      {
          object lockObj = new object();
          int index = 0;
  
          return new Action(async () =&gt;
          {
              while (true)
              {
                  T item;
                  lock (lockObj)
                  {
                      if (index &lt; source.Count)
                      {
                          item = source[index];
                          index++;
                      }
                      else
                          break;
                  }
  
                  int retry = retries;
                  while (retry &gt; 0)
                  {
                      try
                      {
                          bool res = await action(item);
                          if (res)
                              retry = -1;
                          else
                              //sleep if not success..
                              Thread.Sleep(200);
  
                      }
                      catch (Exception e)
                      {
                          LoggerAgent.LogException(e, method);
                      }
                      finally
                      {
                          retry--;
                      }
                  }
              }
          }).RunParallel(threads);
      }
  </code></pre>
  
  <p>RunParallel is an extention method for Action, its look like this:</p>
  
  <pre><code>public static IEnumerable&lt;Task&gt; RunParallel(this Action action, int amount)
      {
          List&lt;Task&gt; tasks = new List&lt;Task&gt;();
          for (int i = 0; i &lt; amount; i++)
          {
              Task task = Task.Factory.StartNew(action);
              tasks.Add(task);
          }
          return tasks;
      }
  </code></pre>
  
  <p>Now, the issue: The thread is just disappearing or collapsing without waiting for the action to finish.</p>
  
  <p>I wrote this example code:</p>
  
  <pre><code>private static async Task ex()
      {
          List&lt;int&gt; ints = new List&lt;int&gt;();
          for (int i = 0; i &lt; 1000; i++)
          {
              ints.Add(i);
          }
  
          var tasks = RetryComponent.RunWithRetries(ints, 100, async (num) =&gt;
          {
              try
              {
                  List&lt;string&gt; test = await fetchSmthFromDb();
                  Console.WriteLine("#" + num + "  " + test[0]);
                  return test[0] == "test";
              }
              catch (Exception e)
              {
                  Console.WriteLine(e.StackTrace);
                  return false;
              }
  
          }, 5, "test");
  
          await Task.WhenAll(tasks);
      }
  </code></pre>
  
  <p>The <code>fetchSmthFromDb</code> is a simple Task> which fetches something from the db and works perfectly fine when invoked outside of this example.</p>
  
  <p>Whenever the <code>List&lt;string&gt; test = await fetchSmthFromDb();</code> row is invoked, the thread seems to be closing and the <code>Console.WriteLine("#" + num + "  " + test[0]);</code> not even being triggered, also when debugging the breakpoint never hit.</p>
  
  <p><strong>The Final Working Code</strong></p>
  
  <pre><code>private static async Task DoWithRetries(Func&lt;Task&gt; action, int retryCount, string method)
      {
          while (true)
          {
              try
              {
                  await action();
                  break;
              }
              catch (Exception e)
              {
                  LoggerAgent.LogException(e, method);
              }
  
              if (retryCount &lt;= 0)
                  break;
  
              retryCount--;
              await Task.Delay(200);
          };
      }
  
      public static async Task RunWithRetries&lt;T&gt;(List&lt;T&gt; source, int threads, Func&lt;T, Task&lt;bool&gt;&gt; action, int retries, string method)
      {
          Func&lt;T, Task&gt; newAction = async (item) =&gt;
          {
              await DoWithRetries(async ()=&gt;
              {
                  await action(item);
              }, retries, method);
          };
          await source.ParallelForEachAsync(newAction, threads);
      }
  </code></pre>