You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Worker Service后台服务启动成功但未执行业务代码问题排查

问题诊断与修复方案

你的Worker Service作为Windows服务运行时未执行业务代码,主要由以下几个关键问题导致,逐一修复即可解决:


1. 核心问题点

  • ExecuteAsync方法错误包装异步逻辑:用Task.Run包裹异步任务后直接返回,导致后台服务无法正确跟踪任务执行;
  • DbContext未通过依赖注入管理:手动new TemperatureDbContext未加载配置且生命周期不正确;
  • Program中缺少必要服务注册:未注册DbContext和HttpClientFactory,导致配置读取异常、资源泄漏;
  • Windows服务中无法使用Console输出:Console.WriteLine在服务环境下无输出,无法排查问题;
  • HttpClient重复创建导致资源泄漏:每次请求都新建HttpClient,会耗尽Socket资源;
  • 时间戳冗余处理:ToString后再ParseExact完全没必要,浪费性能。

2. 修复后的代码

Program.cs(完善服务注册)

using Microsoft.EntityFrameworkCore;
using TemperatureService.Entities;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace TemperatureService
{
    public class Program
    {
        static async Task Main(string[] args)
        {
            var host = Host.CreateDefaultBuilder(args)
                .ConfigureServices((context, services) =>
                {
                    // 注册DbContext,从配置读取连接字符串
                    services.AddDbContext<TemperatureDbContext>(options =>
                        options.UseSqlServer(context.Configuration.GetConnectionString("TemperatureDb")));
                    
                    // 注册HttpClient工厂,避免资源泄漏
                    services.AddHttpClient();
                    
                    // 注册后台服务
                    services.AddHostedService<Worker>();
                })
                .UseWindowsService()
                .Build();

            await host.RunAsync();
        }
    }
}

Worker.cs(修正逻辑与依赖注入)

using TemperatureService.Entities;
using Newtonsoft.Json.Linq;
using Microsoft.Extensions.Logging;
using System.Net.Http;

namespace TemperatureService
{
    public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;
        private readonly TemperatureDbContext _dbContext;
        private readonly IHttpClientFactory _httpClientFactory;
        private const string _apiUrl = "http://10.10.30.249/state";
        private const string _sensorIp = "10.10.30.249";

        // 通过构造函数注入所有依赖
        public Worker(ILogger<Worker> logger, TemperatureDbContext dbContext, IHttpClientFactory httpClientFactory)
        {
            _logger = logger;
            _dbContext = dbContext;
            _httpClientFactory = httpClientFactory;
        }

        // 直接实现异步逻辑,无需Task.Run包装
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("Temperature service started at: {Time}", DateTimeOffset.Now);

            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    // 使用HttpClient工厂创建客户端
                    var httpClient = _httpClientFactory.CreateClient();
                    var json = await GetTemperatureAsync(httpClient, _apiUrl, stoppingToken);
                    var responseJson = JObject.Parse(json);

                    var sensorsArray = responseJson["multiSensor"]["sensors"];
                    _logger.LogDebug("Received sensor data: {Sensors}", sensorsArray);

                    // 直接使用当前时间,无需冗余转换
                    var timestamp = DateTime.UtcNow; // 建议用UtcNow避免时区问题

                    var sensorData = new TemperatureSensorData
                    {
                        Value = (double)sensorsArray[0]["value"] / 100,
                        Trend = (int)sensorsArray[0]["trend"],
                        State = (int)sensorsArray[0]["state"],
                        ElapsedTimeS = (int)sensorsArray[0]["elapsedTimeS"],
                        TimeStamp = timestamp,
                        IpAddress = _sensorIp
                    };

                    _dbContext.Temperatures.Add(sensorData);
                    await _dbContext.SaveChangesAsync(stoppingToken);

                    _logger.LogInformation("Saved sensor data at: {Time}", timestamp);
                    await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error processing temperature data");
                    // 出错后延迟再重试,避免频繁报错
                    await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
                }
            }

            _logger.LogInformation("Temperature service stopped at: {Time}", DateTimeOffset.Now);
        }

        private async Task<string> GetTemperatureAsync(HttpClient httpClient, string url, CancellationToken cancellationToken)
        {
            var response = await httpClient.GetAsync(url, cancellationToken);
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync(cancellationToken);
        }
    }
}

3. 额外配置说明

  1. appsettings.json中添加连接字符串:
{
  "ConnectionStrings": {
    "TemperatureDb": "Server=你的数据库地址;Database=TemperatureDb;Trusted_Connection=True;TrustServerCertificate=True;"
  }
}
  1. 查看服务日志:可以通过Windows事件查看器(事件查看器 -> 应用程序和服务日志 -> .NET Runtime)查看ILogger输出的日志,方便排查问题。

内容的提问来源于stack exchange,提问作者Tommy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 20:48:19