0Pricing
C# Academy · 课时

Worker Service 项目

创建独立的 Worker Service,配置 DI 和日志记录,并将其部署为 Windows 服务或 Linux 守护进程。

Worker Service 项目 是 CoddyKit 上的免费 C# Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 4 节课。

什么是 Worker 服务

Worker 服务是用于构建长期运行后台应用的 .NET 项目模板——不包含 Web 服务器或 HTTP 端点。它是一种轻量级主机,非常适合队列处理器、计划任务和守护进程式服务。

创建 Worker 服务

使用 CLI 模板搭建 Worker 服务项目。它会生成一个最简的 Program.cs,以及一个继承自 BackgroundService 的 Worker.cs 类。

# Create a new Worker Service project
dotnet new worker -n OrderProcessor

# Generated structure:
# OrderProcessor/
#   Program.cs       — host configuration
#   Worker.cs        — your BackgroundService subclass
#   appsettings.json

Worker 服务的 Program.cs

生成的 Program.cs 使用通用主机。您可以配置 DI、日志记录和配置系统,并注册工作程序——这与 ASP.NET Core 完全相同,只是不包含 Web 服务器。

using Microsoft.Extensions.Hosting;

var builder = Host.CreateApplicationBuilder(args);

// Register services
builder.Services.AddDbContext<AppDbContext>(opt =>
    opt.UseSqlServer(builder.Configuration.GetConnectionString("Default")));

builder.Services.AddScoped<IOrderRepository, OrderRepository>();
builder.Services.AddHostedService<OrderProcessorWorker>();

var host = builder.Build();
host.Run();

Worker 类

继承 BackgroundService 并实现 ExecuteAsync。主机会在启动时调用它,并传入一个在关闭时触发的取消令牌。

public class OrderProcessorWorker : BackgroundService
{
    private readonly IServiceScopeFactory _factory;
    private readonly ILogger<OrderProcessorWorker> _logger;

    public OrderProcessorWorker(
        IServiceScopeFactory factory,
        ILogger<OrderProcessorWorker> logger)
    {
        _factory = factory;
        _logger  = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken ct)
    {
        while (!ct.IsCancellationRequested)
        {
            using var scope = _factory.CreateScope();
            var repo = scope.ServiceProvider.GetRequiredService<IOrderRepository>();
            var pending = await repo.GetPendingAsync(ct);
            foreach (var order in pending)
                await ProcessOrderAsync(order, ct);
            await Task.Delay(TimeSpan.FromSeconds(10), ct);
        }
    }

    private Task ProcessOrderAsync(Order o, CancellationToken ct) =>
        Task.Delay(100, ct); // placeholder
}

Worker 中的配置与 DI

Worker 服务支持完整的 .NET 配置系统,包括应用设置、环境变量和用户机密。请注入 IConfiguration 或强类型选项。

builder.Services.Configure<WorkerSettings>(
    builder.Configuration.GetSection("Worker"));

public class OrderProcessorWorker : BackgroundService
{
    private readonly WorkerSettings _settings;

    public OrderProcessorWorker(IOptions<WorkerSettings> opts, ...)
        => _settings = opts.Value;

    protected override async Task ExecuteAsync(CancellationToken ct)
    {
        while (!ct.IsCancellationRequested)
        {
            // ...
            await Task.Delay(_settings.PollIntervalSeconds * 1000, ct);
        }
    }
}

Worker 服务中的日志记录

通用主机会自动配置日志记录。请使用 ILogger<T> 进行结构化日志记录。在生产环境中,请配置 Serilog、Application Insights 或其他提供程序。

// Add Serilog to a Worker Service
builder.Host.UseSerilog((ctx, logConfig) =>
    logConfig
        .ReadFrom.Configuration(ctx.Configuration)
        .WriteTo.Console()
        .WriteTo.Seq(ctx.Configuration["Seq:ServerUrl"]!));

// Structured logging in the worker:
_logger.LogInformation("Processing {Count} orders at {Time}",
    orders.Count, DateTimeOffset.UtcNow);
_logger.LogError(ex, "Failed to process order {OrderId}", order.Id);

作为 Windows 服务运行

使用 UseWindowsService() 将 Worker 作为 Windows 服务运行。该服务会随操作系统启动和停止,并且在用户注销后仍能继续运行。

// dotnet add package Microsoft.Extensions.Hosting.WindowsServices

builder.Services.AddWindowsService(options =>
    options.ServiceName = "OrderProcessor");

// Build and publish:
// dotnet publish -c Release -o ./publish

// Install as Windows Service:
// sc create OrderProcessor binpath="C:\services\publish\OrderProcessor.exe"
// sc start OrderProcessor

作为 Linux Systemd 守护进程运行

使用 UseSystemd() 与 Linux 上的 systemd 集成。该服务会接收正确的停止信号,并与 journald 日志记录集成。

// dotnet add package Microsoft.Extensions.Hosting.Systemd

builder.Services.AddSystemd();

// Systemd unit file: /etc/systemd/system/orderprocessor.service
// [Unit]
// Description=Order Processor Worker
// [Service]
// Type=notify
// ExecStart=/usr/bin/dotnet /app/OrderProcessor.dll
// Restart=always
// [Install]
// WantedBy=multi-user.target

// Commands:
// sudo systemctl enable orderprocessor
// sudo systemctl start orderprocessor
// sudo journalctl -u orderprocessor -f

在 Docker 中运行

Worker 服务非常适合 Docker 容器——无需进行端口映射,只需让进程持续循环运行,直到容器停止。

# Dockerfile
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app

FROM mcr.microsoft.com/dotnet/runtime:9.0
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "OrderProcessor.dll"]

# docker-compose.yml:
# services:
#   worker:
#     build: .
#     environment:
#       - ConnectionStrings__Default=Server=db;...
#     depends_on: [db]

实际案例:电子邮件摘要工作程序

一个完整的工作程序,它从数据库中读取数据,并通过电子邮件服务发送每日电子邮件摘要。

public class EmailDigestWorker : BackgroundService
{
    private readonly IServiceScopeFactory _factory;
    private readonly ILogger<EmailDigestWorker> _log;

    protected override async Task ExecuteAsync(CancellationToken ct)
    {
        // Run daily at midnight UTC
        while (!ct.IsCancellationRequested)
        {
            var now = DateTime.UtcNow;
            var next = now.Date.AddDays(1); // next midnight
            await Task.Delay(next - now, ct);

            using var scope = _factory.CreateScope();
            var mailer = scope.ServiceProvider.GetRequiredService<IDigestMailer>();

            try   { await mailer.SendDailyDigestsAsync(ct); }
            catch (Exception ex) { _log.LogError(ex, "Digest failed"); }
        }
    }
}

快速检查

Worker 服务项目与 ASP.NET Core Web API 项目之间的主要区别是什么?

回顾:Worker 服务项目

关键要点:

  • Worker 服务 = 通用主机 + BackgroundService,不包含 Web 服务器
  • 完整支持 DI、日志记录和配置,但不包含 HTTP
  • 使用 UseWindowsService() 部署为 Windows 服务
  • 使用 UseSystemd() 部署为 Linux 守护进程,并与 journald 集成
  • 部署到 Docker 容器中,以执行云原生后台处理
  • 始终在 Worker 中使用 IServiceScopeFactory 处理作用域依赖项

常见问题解答

「Worker Service 项目」课时是免费的吗?

是的 — 「Worker Service 项目」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 4 节课。

「Worker Service 项目」这节课中我会学到什么?

创建独立的 Worker Service,配置 DI 和日志记录,并将其部署为 Windows 服务或 Linux 守护进程。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C# Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「Worker Service 项目」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 C# Academy 课中编写并运行代码吗?

能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. IHostedService 与 BackgroundService
  2. Worker Service 项目
  3. 周期性任务与计时器
  4. Quartz.NET 计划任务
← 返回 C# Academy