Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/core/compatibility/10.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
Original file line number Diff line number Diff line change
@@ -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

<xref:Microsoft.Extensions.Hosting.BackgroundService> now runs the entirety of <xref:Microsoft.Extensions.Hosting.BackgroundService.ExecuteAsync%2A> 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 <xref:Microsoft.Extensions.Hosting.IHostedLifecycleService?displayProperty=fullName> on your `BackgroundService`.
- Forgo `BackgroundService` entirely and implement your own <xref:Microsoft.Extensions.Hosting.IHostedService?displayProperty=fullName>.

## Affected APIs

- <xref:Microsoft.Extensions.Hosting.BackgroundService.ExecuteAsync%2A?displayProperty=fullName>
2 changes: 2 additions & 0 deletions docs/core/compatibility/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down