diff --git a/docs/core/compatibility/10.0.md b/docs/core/compatibility/10.0.md index 7d0c66625293f..4a55d76c7dc8a 100644 --- a/docs/core/compatibility/10.0.md +++ b/docs/core/compatibility/10.0.md @@ -74,6 +74,7 @@ If you're migrating an app to .NET 10, the breaking changes listed here might af | Title | Type of change | Introduced version | |-------|---------------------|--------------------| +| [BackgroundService runs all of ExecuteAsync as a Task](extensions/10.0/backgroundservice-executeasync-task.md) | Behavioral change | Preview 1 | | [Null values preserved in configuration](extensions/10.0/configuration-null-values-preserved.md) | Behavioral change | Preview 7 | | [Message no longer duplicated in Console log output](extensions/10.0/console-json-logging-duplicate-messages.md) | Behavioral change | Preview 7 | | [ProviderAliasAttribute moved to Microsoft.Extensions.Logging.Abstractions assembly](extensions/10.0/provideraliasattribute-moved-assembly.md) | Source incompatible | Preview 4 | diff --git a/docs/core/compatibility/extensions/10.0/backgroundservice-executeasync-task.md b/docs/core/compatibility/extensions/10.0/backgroundservice-executeasync-task.md new file mode 100644 index 0000000000000..a41155ff77ced --- /dev/null +++ b/docs/core/compatibility/extensions/10.0/backgroundservice-executeasync-task.md @@ -0,0 +1,44 @@ +--- +title: "Breaking change: BackgroundService runs all of ExecuteAsync as a Task" +description: "Learn about the breaking change in .NET 10 where BackgroundService now runs the entirety of ExecuteAsync on a background thread instead of running the synchronous portion on the main thread." +ms.date: 10/13/2025 +ai-usage: ai-assisted +ms.custom: https://github.com/dotnet/runtime/issues/116181 +--- + +# BackgroundService runs all of ExecuteAsync as a Task + + now runs the entirety of on a background thread. Previously, the synchronous portion of `ExecuteAsync` (before the first `await`) ran on the main thread during service startup, blocking other services from starting. Only code after the first `await` ran on a background thread. + +## Version introduced + +.NET 10 + +## Previous behavior + +Previously, the synchronous portion of `ExecuteAsync` ran on the main thread and blocked other services from starting. + +## New behavior + +Starting in .NET 10, all of `ExecuteAsync` runs on a background thread, and no part of it blocks other services from starting. + +## Type of breaking change + +This change is a [behavioral change](../../categories.md#behavioral-change). + +## Reason for change + +The previous behavior was a common pitfall that didn't meet user expectations. Most implementers of `BackgroundService` didn't understand that the synchronous portion before the first `await` blocked other services from starting during application startup. + +## Recommended action + +If you require any part of your `BackgroundService.ExecuteAsync` to run earlier during startup (synchronously and blocking other services), you can do any one of the following: + +- Place the code that needs to run synchronously in the constructor, and it executes as part of the service construction. +- Override `StartAsync` and do some work before calling `base.StartAsync`. `StartAsync` retains the behavior that its synchronous portion runs synchronously during startup and blocks other services from starting. +- If you want to run code at a more specific time during service startup, implement on your `BackgroundService`. +- Forgo `BackgroundService` entirely and implement your own . + +## Affected APIs + +- diff --git a/docs/core/compatibility/toc.yml b/docs/core/compatibility/toc.yml index 18c08be85a233..9336afe940e56 100644 --- a/docs/core/compatibility/toc.yml +++ b/docs/core/compatibility/toc.yml @@ -84,6 +84,8 @@ items: href: /ef/core/what-is-new/ef-core-10.0/breaking-changes?toc=/dotnet/core/compatibility/toc.json&bc=/dotnet/breadcrumb/toc.json - name: Extensions items: + - name: BackgroundService runs all of ExecuteAsync as a Task + href: extensions/10.0/backgroundservice-executeasync-task.md - name: Message no longer duplicated in Console log output href: extensions/10.0/console-json-logging-duplicate-messages.md - name: Null values preserved in configuration