/worker-services
Build long-running .NET background services with `BackgroundService`, Generic Host, graceful shutdown, configuration, logging, and deployment patterns suited to workers and daemons. USE FOR: background services; scheduled workers; hosted services; worker extraction; graceful
$ npx -y skills add managedcode/dotnet-skills --skill worker-services --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/worker-services
Context preview
The summary Claude sees to decide when to auto-load this skill.
Build long-running .NET background services with `BackgroundService`, Generic Host, graceful shutdown, configuration, logging, and deployment patterns suited to workers and daemons. USE FOR: background services; scheduled workers; hosted services; worker extraction; graceful
SKILL.md
worker-services.SKILL.mdname: worker-services
description: "Build long-running .NET background services with `BackgroundService`, Generic Host, graceful shutdown, configuration, logging, and deployment patterns suited to workers and daemons. USE FOR: background services; scheduled workers; hosted services; worker extraction; graceful shutdown, health checks, and service hosting review. DO NOT USE FOR: unrelated stacks; generic tasks that do not need this specific guidance. INVOKES: inspect the repository context, edit targeted files, and run relevant build, test, lint, or validation commands when changes are made."
compatibility: "Requires a worker, hosted service, or background-processing scenario."
.NET Worker Services
Trigger On
- building long-running background services or scheduled workers
- adding hosted services to an app or extracting them into a worker process
- reviewing graceful shutdown, cancellation, queue processing, or health behavior
Documentation
- [Worker Services in .NET](https://learn.microsoft.com/en-us/dotnet/core/extensions/workers)
- [Background tasks with hosted services in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-10.0)
- [Create Windows Service using BackgroundService](https://learn.microsoft.com/en-us/dotnet/core/extensions/windows-service)
- [App health checks in .NET](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/diagnostic-health-checks)
- [Health checks in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-10.0)
References
- [patterns.md](references/patterns.md) - BackgroundService patterns, graceful shutdown, and health check implementations
- [anti-patterns.md](references/anti-patterns.md) - Common worker service mistakes and how to avoid them
Workflow
1. **Use BackgroundService as your base class:**
- Provides standard `StartAsync`/`StopAsync` handling
- Focus on implementing `ExecuteAsync` only
- Proper cancellation token management built-in
2. **Handle scoped dependencies correctly:**
- Create service scopes for scoped services
- No scope is created by default in hosted services
3. **Implement graceful shutdown:**
- Propagate cancellation tokens throughout
- Complete work promptly when token fires
- Avoid ungraceful shutdown at timeout
4. **Keep execution loop thin:**
- Move business logic to testable services
- Handle exceptions to prevent service crashes
- Use `PeriodicTimer` for scheduled work
5. **Add observability:**
- Use health checks for readiness/liveness
- Expose metrics and structured logging
- Consider distributed locks for multi-instance
Current Upstream Notes
- `.NET runtime` `v10.0.10` is servicing. For workers, rerun cancellation, graceful shutdown, long-running GC/pinning, EventPipe diagnostics, NativeAOT, and platform-specific filesystem/drive checks after upgrading rather than changing architecture by default.
- Use the refreshed Worker Services and hosted-service Learn pages for exact current hosting and health-check APIs when adding new worker entry points.
Basic BackgroundService Pattern
Simple Worker
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
public Worker(ILogger<Worker> logger)
{
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Worker starting");
while (!stoppingToken.IsCancellationRequested)
{
try
{
_logger.LogInformation("Worker running at: {Time}", DateTimeOffset.Now);
await DoWorkAsync(stoppingToken);
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
}
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
{
// Graceful shutdown, not an error
break;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in worker iteration");
// Continue or break based on error severity
}
}
_logger.LogInformation("Worker stopping");
}
private async Task DoWorkAsync(CancellationToken cancellationToken)
{
// Business logic here
}
}Using PeriodicTimer (Recommended)
public class TimedWorker : BackgroundService
{
private readonly ILogger<TimedWorker> _logger;
private readonly IServiceScopeFactory _scopeFactory;
private readonly TimeSpan _period = TimeSpan.FromMinutes(1);
public TimedWorker(ILogger<TimedWorker> logger, IServiceScopeFactory scopeFactory)
{
_logger = logger;
_scopeFactory = scopeFactory;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
using var timer = new PeriodicTimer(_period);
while (await timer.WaitForNextTickAsync(stoppingToken))
{
try
{
await using var scope = _scopeFactory.CreateAsyncScope();
var processor = scope.ServiceProvider.GetRequiredService<IDataProcessor>();
await processor.ProcessAsync(stoppingToken);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing scheduled task");
}
}
}
}Handling Scoped Dependencies
Correct Pattern with Scope Factory
public class ScopedWorker : BackgroundService
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly ILogger<ScopedWorker> _logger;
public ScopedWorker(IServiceScopeFactory scopeFactory, ILogger<ScopedWorker> logger)
{
_scopeFactory = scopeFactory;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{Read more
name: worker-services description: "Build long-running .NET background services with `BackgroundService`, Generic Host, graceful shutdown, configuration, logging, and deployment patterns suited to workers and daemons. USE FOR: background services; scheduled workers; hosted services; worker extraction; graceful shutdown, health checks, and service hosting review. DO NOT USE FOR: unrelated stacks; generic tasks that do not need this specific guidance. INVOKES: inspect the repository context, edit targeted files, and run relevant build, test, lint, or validation commands when changes are made." compatibility: "Requires a worker, hosted service, or background-processing scenario."
.NET Worker Services
Trigger On
- building long-running background services or scheduled workers
- adding hosted services to an app or extracting them into a worker process
- reviewing graceful shutdown, cancellation, queue processing, or health behavior
Documentation
- [Worker Services in .NET](https://learn.microsoft.com/en-us/dotnet/core/extensions/workers)
- [Background tasks with hosted services in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-10.0)
- [Create Windows Service using BackgroundService](https://learn.microsoft.com/en-us/dotnet/core/extensions/windows-service)
- [App health checks in .NET](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/diagnostic-health-checks)
- [Health checks in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-10.0)
References
- [patterns.md](references/patterns.md) - BackgroundService patterns, graceful shutdown, and health check implementations
- [anti-patterns.md](references/anti-patterns.md) - Common worker service mistakes and how to avoid them
Workflow
1. **Use BackgroundService as your base class:**
- Provides standard `StartAsync`/`StopAsync` handling
- Focus on implementing `ExecuteAsync` only
- Proper cancellation token management built-in
2. **Handle scoped dependencies correctly:**
- Create service scopes for scoped services
- No scope is created by default in hosted services
3. **Implement graceful shutdown:**
- Propagate cancellation tokens throughout
- Complete work promptly when token fires
- Avoid ungraceful shutdown at timeout
4. **Keep execution loop thin:**
- Move business logic to testable services
- Handle exceptions to prevent service crashes
- Use `PeriodicTimer` for scheduled work
5. **Add observability:**
- Use health checks for readiness/liveness
- Expose metrics and structured logging
- Consider distributed locks for multi-instance
Current Upstream Notes
- `.NET runtime` `v10.0.10` is servicing. For workers, rerun cancellation, graceful shutdown, long-running GC/pinning, EventPipe diagnostics, NativeAOT, and platform-specific filesystem/drive checks after upgrading rather than changing architecture by default.
- Use the refreshed Worker Services and hosted-service Learn pages for exact current hosting and health-check APIs when adding new worker entry points.
Basic BackgroundService Pattern
Simple Worker
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
public Worker(ILogger<Worker> logger)
{
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Worker starting");
while (!stoppingToken.IsCancellationRequested)
{
try
{
_logger.LogInformation("Worker running at: {Time}", DateTimeOffset.Now);
await DoWorkAsync(stoppingToken);
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
}
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
{
// Graceful shutdown, not an error
break;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in worker iteration");
// Continue or break based on error severity
}
}
_logger.LogInformation("Worker stopping");
}
private async Task DoWorkAsync(CancellationToken cancellationToken)
{
// Business logic here
}
}Using PeriodicTimer (Recommended)
public class TimedWorker : BackgroundService
{
private readonly ILogger<TimedWorker> _logger;
private readonly IServiceScopeFactory _scopeFactory;
private readonly TimeSpan _period = TimeSpan.FromMinutes(1);
public TimedWorker(ILogger<TimedWorker> logger, IServiceScopeFactory scopeFactory)
{
_logger = logger;
_scopeFactory = scopeFactory;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
using var timer = new PeriodicTimer(_period);
while (await timer.WaitForNextTickAsync(stoppingToken))
{
try
{
await using var scope = _scopeFactory.CreateAsyncScope();
var processor = scope.ServiceProvider.GetRequiredService<IDataProcessor>();
await processor.ProcessAsync(stoppingToken);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing scheduled task");
}
}
}
}Handling Scoped Dependencies
Correct Pattern with Scope Factory
public class ScopedWorker : BackgroundService
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly ILogger<ScopedWorker> _logger;
public ScopedWorker(IServiceScopeFactory scopeFactory, ILogger<ScopedWorker> logger)
{
_scopeFactory = scopeFactory;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{Stop explaining .NET to your AI. Start building. We've all been there: asking Claude to use Entity Framework, only to get EF6 patterns in a .NET 8 project. Explaining to Copilot that Blazor Server and Blazor WebAssembly aren't the same thing.
Repo: managedcode/dotnet-skills
Other skills on dotnet-skills.
- /aspnet-core
Build, debug, modernize, or review ASP.NET Core applications with correct hosting, middleware, security, configuration, logging, and deployment patterns on current .NET. USE FOR: working on ASP.NET Core apps, services, or middleware; changing auth, routing, configuration,
Open skill - /aspire
Build, upgrade, and operate Aspire 13.4.x C# or TypeScript application hosts with the current CLI, AppHost, ServiceDefaults, integrations, dashboard, testing, MCP, and deployment patterns for distributed apps. USE FOR: Aspire.AppHost.Sdk, Aspire.Hosting.*,
Open skill - /azure-functions
Build, review, or migrate Azure Functions in .NET with correct execution model, isolated worker setup, bindings, DI, and Durable Functions patterns. USE FOR: working on Azure Functions in .NET; migrating from the in-process model to the isolated worker model; adding Durable
Open skill - /blazor
Build and review Blazor applications across server, WebAssembly, web app, and hybrid scenarios with correct component design, state flow, rendering, and hosting choices. USE FOR: building interactive web UIs with C# instead of JavaScript; choosing between Server, WebAssembly, or
Open skill - /entity-framework6
Maintain or migrate EF6-based applications with realistic guidance on what to keep, what to modernize, and when EF Core is or is not the right next step. USE FOR: EF6 codebases; runtime versus ORM migration decisions; EDMX, code-first, ObjectContext, and legacy data-access
Open skill - /entity-framework-core
Design, tune, or review EF Core data access with proper modeling, migrations, query translation, performance, and lifetime management for modern .NET applications. USE FOR: DbContext, migrations, model configuration, EF queries, tracking, loading, performance, transactions, and
Open skill

