title: Should .net core `IHostedService` start a new thread
body: <p>.net core <code>BackgroundService</code> or <code>IHostedService</code>'s start method is async:</p>
  
  <pre class="lang-cs prettyprint-override"><code>//IHostedService
  Task StartAsync(CancellationToken cancellationToken);
  //BackgroundService
  Task ExecuteAsync(CancellationToken stoppingToken);
  </code></pre>
  
  <p>So should I write all the logic in the <code>ExecuteAsync</code>/<code>StartAsync</code> method, or should I just start a new thread and return right away?</p>
  
  <p>For example, which of the following two is the correct implementation?</p>
  
  <p>1.</p>
  
  <pre class="lang-cs prettyprint-override"><code>protected override async Task ExecuteAsync(CancellationToken stoppingToken)
  {
      new Thread(async () =&gt; await DoWork(stoppingToken)).Start();
  
      await Task.CompletedTask;
  }
  
  private async Task DoWork(CancellationToken stoppingToken) 
  {
      while (!stoppingToken.IsCancellationRequested)
          //actual works
  }
  </code></pre>
  
  <p>2.</p>
  
  <pre class="lang-cs prettyprint-override"><code>protected override async Task ExecuteAsync(CancellationToken stoppingToken)
  {
      while (!stoppingToken.IsCancellationRequested)
      {
          //actual works
          await Task.Delay(1000);//e.g
      }
  }
  </code></pre>
  
  <p>Semantically I think the second one seems to be right, but if there're several <code>IHostedService</code>s, can they run in parallel with the second form?</p>
  
  <p><strong>Edit 1</strong></p>
  
  <p>I also write a sample program that illustrate the hosted services aren't themselves run as seperated threads.</p>
  
  <p>The message <code>"Waiting for signal.."</code> won't be written console until I type a <code>q</code>:</p>
  
  <pre class="lang-cs prettyprint-override"><code>using Microsoft.Extensions.Configuration;
  using Microsoft.Extensions.DependencyInjection;
  using Microsoft.Extensions.Hosting;
  using System;
  using System.Threading;
  using System.Threading.Tasks;
  
  namespace BackgroundTaskTest
  {
      public class Program
      {
          public static async Task Main(string[] args)
          {
              var host = new HostBuilder()
                  .ConfigureServices((hostContext, services) =&gt;
                  {
                      IConfiguration config = hostContext.Configuration;
  
                      //register tasks
                      services.AddHostedService&lt;ReadService&gt;();
                      services.AddHostedService&lt;BlockService&gt;();
                  })
                  .UseConsoleLifetime()
                  .Build();
  
              await host.RunAsync();
          }
      }
  
      public static class WaitClass
      {
          public static AutoResetEvent Event = new AutoResetEvent(false);
      }
  
      public class ReadService : BackgroundService
      {
          protected override async Task ExecuteAsync(CancellationToken stoppingToken)
          {
              while (!stoppingToken.IsCancellationRequested)
              {
                  var c = Console.ReadKey();
                  if (c.KeyChar == 'q')
                  {
                      Console.WriteLine("\nTrigger event");
                      WaitClass.Event.Set();
                  }
                  await Task.Delay(1);
              }
          }
      }
  
      public class BlockService : BackgroundService
      {
          protected override Task ExecuteAsync(CancellationToken stoppingToken)
          {
              while (!stoppingToken.IsCancellationRequested)
              {
                  Console.WriteLine("Waiting for signal..");
                  WaitClass.Event.WaitOne();
                  Console.WriteLine("Signal waited");
              }
              return Task.CompletedTask;
          }
      }
  }
  </code></pre>