15

I have implemented a BackgroundService in an ASP.NET Core 2.1 application:

public class MyBackgroundService : BackgroundService
{
    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (true)
        {
            await DoSomethingAsync();
            await Task.Delay(10 * 1000);
        }
        return Task.CompletedTask;
    }
}

I have registered it in my ConfigureServices() method:

services.AddSingleton<MyBackgroundService>();

I am currently (reluctantly) starting it by calling (and not awaiting) the StartAsync() method from within the Configure() method:

app.ApplicationServices.GetService<SummaryCache>().StartAsync(new CancellationToken());

What is the best practice method for starting the long running service?

Creyke
  • 1,887
  • 2
  • 12
  • 16
  • 2
    Check out Steve Gordon's blog: https://www.stevejgordon.co.uk/asp-net-core-2-ihostedservice – juunas Oct 19 '18 at 09:45
  • @junnas This unfortunately appears out of date (ASP.NET 2.0 preview before BackgroundService was made available) and it doesn't explain how to make a service start without explicitly invoking StartAsync() – Creyke Oct 19 '18 at 12:06
  • Would hangfire be an option? https://www.hangfire.io/ – LocEngineer Oct 19 '18 at 12:21
  • I implemented a background service using Steve Gordon's approach that runs on 2.2 preview 2 though? – juunas Oct 19 '18 at 12:28
  • 2
    By default, after registering `services.AddSingleton();`, it will start when application start, there is no need to call `StartAsync()` expecitly from your own code. – Edward Oct 22 '18 at 07:22
  • Possible duplicate of [Proper way to register HostedService in ASP.NET Core. AddHostedService vs AddSingleton](https://stackoverflow.com/questions/51480324/proper-way-to-register-hostedservice-in-asp-net-core-addhostedservice-vs-addsin) – ninjeff Dec 04 '18 at 16:13
  • 3
    Is there any way to stop the background service starting automatically and instead start on demand? – Simon Gymer Feb 27 '20 at 09:38

1 Answers1

27

Explicitly calling StartAsync is not needed.

Calling

services.AddSingleton<MyBackgroundService>();

won't work since all service implementations are resolved via DI through IHostedService interface. edit: e.g. svcProvider.GetServices<IHostedService>() -> IEnumerable<IHostedService>

You need to call either:

services.AddSingleton<IHostedService, MyBackgroundService>();

or

services.AddHostedService<MyBackgroundService>();

edit: AddHostedService also registers an IHostedService: https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.servicecollectionhostedserviceextensions.addhostedservice?view=aspnetcore-2.2

Cosmin Sontu
  • 1,034
  • 11
  • 16
  • 4
    * to discover all background services to be run, the framework relies on DI and would call servcies.GetServcies() which yields IEnumerable. This resolves your service if you register via the Interface. .AddHostedService() does exactly that (https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.servicecollectionhostedserviceextensions.addhostedservice?view=aspnetcore-2.2) – Cosmin Sontu Feb 07 '19 at 17:02
  • 1
    what if for test purposes I want to create multiple instances of background services dynamically based on web API call? then can I call StartAsync? – Saher Ahwal Aug 01 '20 at 00:47