AspNetCore.Docs/aspnetcore/fundamentals/host/hosted-services.md

18 KiB

title author description monikerRange ms.author ms.custom ms.date no-loc uid
Background tasks with hosted services in ASP.NET Core rick-anderson Learn how to implement background tasks with hosted services in ASP.NET Core. >= aspnetcore-2.1 riande mvc 02/10/2020
Home
Privacy
Kestrel
appsettings.json
ASP.NET Core Identity
cookie
Cookie
Blazor
Blazor Server
Blazor WebAssembly
Identity
Let's Encrypt
Razor
SignalR
fundamentals/host/hosted-services

Background tasks with hosted services in ASP.NET Core

By Jeow Li Huan

::: moniker range=">= aspnetcore-3.0"

In ASP.NET Core, background tasks can be implemented as hosted services. A hosted service is a class with background task logic that implements the xref:Microsoft.Extensions.Hosting.IHostedService interface. This topic provides three hosted service examples:

View or download sample code (how to download)

Worker Service template

The ASP.NET Core Worker Service template provides a starting point for writing long running service apps. An app created from the Worker Service template specifies the Worker SDK in its project file:

<Project Sdk="Microsoft.NET.Sdk.Worker">

To use the template as a basis for a hosted services app:

[!INCLUDE]

Package

An app based on the Worker Service template uses the Microsoft.NET.Sdk.Worker SDK and has an explicit package reference to the Microsoft.Extensions.Hosting package. For example, see the sample app's project file (BackgroundTasksSample.csproj).

For web apps that use the Microsoft.NET.Sdk.Web SDK, the Microsoft.Extensions.Hosting package is referenced implicitly from the shared framework. An explicit package reference in the app's project file isn't required.

IHostedService interface

The xref:Microsoft.Extensions.Hosting.IHostedService interface defines two methods for objects that are managed by the host:

  • StartAsync(CancellationToken): StartAsync contains the logic to start the background task. StartAsync is called before:

    The default behavior can be changed so that the hosted service's StartAsync runs after the app's pipeline has been configured and ApplicationStarted is called. To change the default behavior, add the hosted service (VideosWatcher in the following example) after calling ConfigureWebHostDefaults:

    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }
    
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                })
                .ConfigureServices(services =>
                {
                    services.AddHostedService<VideosWatcher>();
                });
    }
    
  • StopAsync(CancellationToken): Triggered when the host is performing a graceful shutdown. StopAsync contains the logic to end the background task. Implement xref:System.IDisposable and finalizers (destructors) to dispose of any unmanaged resources.

    The cancellation token has a default five second timeout to indicate that the shutdown process should no longer be graceful. When cancellation is requested on the token:

    • Any remaining background operations that the app is performing should be aborted.
    • Any methods called in StopAsync should return promptly.

    However, tasks aren't abandoned after cancellation is requested—the caller awaits all tasks to complete.

    If the app shuts down unexpectedly (for example, the app's process fails), StopAsync might not be called. Therefore, any methods called or operations conducted in StopAsync might not occur.

    To extend the default five second shutdown timeout, set:

The hosted service is activated once at app startup and gracefully shut down at app shutdown. If an error is thrown during background task execution, Dispose should be called even if StopAsync isn't called.

BackgroundService base class

xref:Microsoft.Extensions.Hosting.BackgroundService is a base class for implementing a long running xref:Microsoft.Extensions.Hosting.IHostedService.

ExecuteAsync(CancellationToken) is called to run the background service. The implementation returns a xref:System.Threading.Tasks.Task that represents the entire lifetime of the background service. No further services are started until ExecuteAsync becomes asynchronous, such as by calling await. Avoid performing long, blocking initialization work in ExecuteAsync. The host blocks in StopAsync(CancellationToken) waiting for ExecuteAsync to complete.

The cancellation token is triggered when IHostedService.StopAsync is called. Your implementation of ExecuteAsync should finish promptly when the cancellation token is fired in order to gracefully shut down the service. Otherwise, the service ungracefully shuts down at the shutdown timeout. For more information, see the IHostedService interface section.

Timed background tasks

A timed background task makes use of the System.Threading.Timer class. The timer triggers the task's DoWork method. The timer is disabled on StopAsync and disposed when the service container is disposed on Dispose:

[!code-csharp]

The xref:System.Threading.Timer doesn't wait for previous executions of DoWork to finish, so the approach shown might not be suitable for every scenario. Interlocked.Increment is used to increment the execution counter as an atomic operation, which ensures that multiple threads don't update executionCount concurrently.

The service is registered in IHostBuilder.ConfigureServices (Program.cs) with the AddHostedService extension method:

[!code-csharp]

Consuming a scoped service in a background task

To use scoped services within a BackgroundService, create a scope. No scope is created for a hosted service by default.

The scoped background task service contains the background task's logic. In the following example:

  • The service is asynchronous. The DoWork method returns a Task. For demonstration purposes, a delay of ten seconds is awaited in the DoWork method.
  • An xref:Microsoft.Extensions.Logging.ILogger is injected into the service.

[!code-csharp]

The hosted service creates a scope to resolve the scoped background task service to call its DoWork method. DoWork returns a Task, which is awaited in ExecuteAsync:

[!code-csharp]

The services are registered in IHostBuilder.ConfigureServices (Program.cs). The hosted service is registered with the AddHostedService extension method:

[!code-csharp]

Queued background tasks

A background task queue is based on the .NET 4.x xref:System.Web.Hosting.HostingEnvironment.QueueBackgroundWorkItem*:

[!code-csharp]

In the following QueueHostedService example:

  • The BackgroundProcessing method returns a Task, which is awaited in ExecuteAsync.
  • Background tasks in the queue are dequeued and executed in BackgroundProcessing.
  • Work items are awaited before the service stops in StopAsync.

[!code-csharp]

A MonitorLoop service handles enqueuing tasks for the hosted service whenever the w key is selected on an input device:

  • The IBackgroundTaskQueue is injected into the MonitorLoop service.
  • IBackgroundTaskQueue.QueueBackgroundWorkItem is called to enqueue a work item.
  • The work item simulates a long-running background task:

[!code-csharp]

The services are registered in IHostBuilder.ConfigureServices (Program.cs). The hosted service is registered with the AddHostedService extension method:

[!code-csharp]

MonitorLoop is started in Program.Main:

[!code-csharp]

::: moniker-end

::: moniker range="< aspnetcore-3.0"

In ASP.NET Core, background tasks can be implemented as hosted services. A hosted service is a class with background task logic that implements the xref:Microsoft.Extensions.Hosting.IHostedService interface. This topic provides three hosted service examples:

View or download sample code (how to download)

Package

Reference the Microsoft.AspNetCore.App metapackage or add a package reference to the Microsoft.Extensions.Hosting package.

IHostedService interface

Hosted services implement the xref:Microsoft.Extensions.Hosting.IHostedService interface. The interface defines two methods for objects that are managed by the host:

The hosted service is activated once at app startup and gracefully shut down at app shutdown. If an error is thrown during background task execution, Dispose should be called even if StopAsync isn't called.

Timed background tasks

A timed background task makes use of the System.Threading.Timer class. The timer triggers the task's DoWork method. The timer is disabled on StopAsync and disposed when the service container is disposed on Dispose:

[!code-csharp]

The xref:System.Threading.Timer doesn't wait for previous executions of DoWork to finish, so the approach shown might not be suitable for every scenario.

The service is registered in Startup.ConfigureServices with the AddHostedService extension method:

[!code-csharp]

Consuming a scoped service in a background task

To use scoped services within an IHostedService, create a scope. No scope is created for a hosted service by default.

The scoped background task service contains the background task's logic. In the following example, an xref:Microsoft.Extensions.Logging.ILogger is injected into the service:

[!code-csharp]

The hosted service creates a scope to resolve the scoped background task service to call its DoWork method:

[!code-csharp]

The services are registered in Startup.ConfigureServices. The IHostedService implementation is registered with the AddHostedService extension method:

[!code-csharp]

Queued background tasks

A background task queue is based on the .NET Framework 4.x xref:System.Web.Hosting.HostingEnvironment.QueueBackgroundWorkItem* (tentatively scheduled to be built-in for ASP.NET Core):

[!code-csharp]

In QueueHostedService, background tasks in the queue are dequeued and executed as a BackgroundService, which is a base class for implementing a long running IHostedService:

[!code-csharp]

The services are registered in Startup.ConfigureServices. The IHostedService implementation is registered with the AddHostedService extension method:

[!code-csharp]

In the Index page model class:

[!code-csharp]

When the Add Task button is selected on the Index page, the OnPostAddTask method is executed. QueueBackgroundWorkItem is called to enqueue a work item:

[!code-csharp]

::: moniker-end

Additional resources