为何C#后台服务以服务运行失败,以可执行文件运行正常?
.NET Core Windows服务触发
System.OperationCanceledException异常问题 我用C#开发了一个后台服务,上周部署到虚拟机,通过sc.exe create NameOfService binPath= blabla命令创建服务后运行正常,直到2023年2月13日(周日)23:58出现异常。直接运行.exe文件一切正常,但以服务形式启动就会触发以下异常:
Application: SE.Worker.SystemStatus.exe CoreCLR Version: 4.700.20.11803 .NET Core Version: 3.1.3 Description: The process was terminated due to an unhandled exception. Exception Info: System.OperationCanceledException: The operation was canceled. at System.Threading.CancellationToken.ThrowOperationCanceledException() at Microsoft.Extensions.Hosting.Internal.Host.StopAsync(CancellationToken cancellationToken) at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.WaitForShutdownAsync(IHost host, CancellationToken token) at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token) at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token) at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host) at SE.Worker.SystemStatus.Program.Main(String[] args) in D:\App\Solution\SE.Worker.SystemStatus\Program.cs:line 12
相关代码
Program.cs
public static void Main(string[] args) => CreateHostBuilder(args).Build().Run(); public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args).UseWindowsService() .ConfigureLogging(logging => { logging.ClearProviders(); logging.AddConsole(); logging.AddEventLog(); }) // Essential to run this as a window service .ConfigureServices(configureServices); private static void configureServices(HostBuilderContext context, IServiceCollection services) { services.Configure<StatusConfig>(context.Configuration.GetSection("Status")); services.AddLogging(); services.AddSingleton<IVersionProcess, SystemStatusProcess>(); services.AddHostedService<SystemStatusWorker>(); }
SystemStatusWorker.cs
public class SystemStatusWorker : BackgroundService { private readonly ISystemStatusProcess systemStatusProcess; private readonly ILogger<SystemStatusWorker> logger; public SystemStatusWorker(ISystemStatusProcess systemStatusProcess, ILogger<SystemStatusWorker> logger) { this.systemStatusProcess = systemStatusProcess; this.logger = logger; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { logger.LogInformation("SystemStatus Worker running at: {time}", DateTimeOffset.Now); await systemStatusProcess.GetSystemStatus(); } } }
可能的原因及解决方案
- 服务启动超时被系统终止
Windows服务默认有30秒的启动超时限制,如果systemStatusProcess.GetSystemStatus()执行时间过长,或服务初始化耗时超过阈值,系统会强制终止服务并触发取消异常。
- 解决:检查
GetSystemStatus()是否存在长时间阻塞操作,优化代码确保异步执行;或修改注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control下的ServicesPipeTimeout值(单位毫秒,例如设为60000即60秒)调整超时时间。
- 未在业务方法中响应取消令牌
虽然ExecuteAsync方法检查了stoppingToken,但GetSystemStatus()内部未处理取消请求,当服务被要求停止时,Host的StopAsync等待超时后抛出异常。
- 解决:将
stoppingToken传入GetSystemStatus(),在方法内部的IO操作、循环中加入stoppingToken.ThrowIfCancellationRequested()或检查IsCancellationRequested状态,及时响应取消指令:
await systemStatusProcess.GetSystemStatus(stoppingToken);
- 日志配置适配问题
服务环境中没有控制台窗口,添加Console日志提供器可能引发潜在错误,间接导致服务终止。
- 解决:移除
logging.AddConsole(),仅保留EventLog;或通过条件判断仅在非服务模式下添加Console日志:
if (!WindowsServiceHelpers.IsWindowsService()) { logging.AddConsole(); }
- 服务账户权限不足
直接运行.exe使用当前用户权限,而Windows服务默认使用受限账户(如Local System),可能导致GetSystemStatus()中访问文件、数据库或系统资源的操作失败,引发服务终止。
- 解决:检查服务运行账户的权限,赋予必要资源的访问权限;在
GetSystemStatus()中添加详细日志,定位具体失败的操作环节。
内容的提问来源于stack exchange,提问作者Paul Viorel
相关产品推荐
相关产品推荐

