Skip to content

[Breaking change]: BackgroundService runs all of ExecuteAsync as a Task #48878

@ericstj

Description

@ericstj

Description

See dotnet/runtime#36063
dotnet/runtime#116283, dotnet/runtime#116181

BackgroundService will now run all of ExecuteAsync on a background thread.

We previously would run the synchronous portion of ExecuteAsync on the main thread during service startup, blocking other services from starting, and only things after the first await would run on a background thread.

This was meant to give the implementers of BackgroundService the ability to partition some synchronous work before the first await and async work after.

What we found was that most implementers of BackgroundService did not understand or expect this nuance. To avoid this common pitfall we've moved the entirety of ExecuteAsync to the background.

Version

.NET 10

Previous behavior

The synchronous portion of ExecuteAsync would run on the main thread and block other services from starting.

New behavior

All of ExecuteAsync now runs on a background thread.

Type of breaking change

  • Binary incompatible: Existing binaries might encounter a breaking change in behavior, such as failure to load or execute, and if so, require recompilation.
  • Source incompatible: When recompiled using the new SDK or component or to target the new runtime, existing source code might require source changes to compile successfully.
  • Behavioral change: Existing binaries might behave differently at run time.

Reason for change

Common pitfall, did not meet user's expectations.

Recommended action

If you require any part of your BackgroundService.ExecuteAsync to run earlier, you can do any one of the following:

  1. Place that in the constructor and it will execute as part of the service construction.
  2. Override StartAsync and do some work before calling base.StartAsync. StartAsync retains the behavior that it's synchronous portion will run synchronously during startup and block other services from starting.
  3. Implement IHostedLifecycleService on your BackgroundService if you wish to run something at a more specific time during service startup.
  4. Forgo BackgroundService entirely and implement your own IHostedService

Feature area

Extensions

Affected APIs

Microsoft.Extensions.Hosting


Associated WorkItem - 495675

Metadata

Metadata

Labels

📌 seQUESTeredIdentifies that an issue has been imported into Quest.breaking-changeIndicates a .NET Core breaking change

Type

No type

Projects

Status

✅ Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions