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

同一IHostedService实例的StartAsync被调用两次问题求助

问题现象

注册多个IHostedService实例时,第一个实例的StartAsync方法被调用两次,第二个实例的该方法未触发,但两个实例的构造函数均已执行。

相关代码

Program.cs

services.AddSingleton<IHostedService, ProductService>(provider => (ProductService)provider.GetService<IProductService>()!);
services.AddSingleton<IProductService, ProductService>();
services.AddSingleton<IHostedService, ProductService>(provider => (ProductService)provider.GetService<IProductService>()!);
services.AddSingleton<IProductService, ProductService>();

ProductService.cs

public class ProductService : IProductService, IHostedService
{
    public async Task StartAsync(CancellationToken cancellationToken) { }
    public async Task StopAsync(CancellationToken cancellationToken) { }
}

问题原因

当前注册逻辑存在核心问题:

  1. IProductService被注册为单例(Singleton),因此两次调用provider.GetService<IProductService>()拿到的是同一个实例。
  2. 两次注册IHostedService时,都指向了这个唯一的ProductService实例,相当于把同一个对象重复注册为IHostedService。宿主启动时会遍历所有IHostedService条目调用StartAsync,导致同一个实例的方法被执行两次,而你期望的第二个独立实例根本没有被创建。

解决方案

要创建多个独立的ProductService实例,需确保每个IHostedService注册对应不同的实例,以下是几种可行实现方式:

方式一:工厂函数直接生成新实例

如果ProductService无需依赖注入,或可直接构造,每次注册IHostedService时返回新实例:

// 注册第一个独立实例
services.AddSingleton<IHostedService>(_ => new ProductService());
// 注册第二个独立实例
services.AddSingleton<IHostedService>(_ => new ProductService());

方式二:手动绑定实例到双服务类型

如果需要同时将每个ProductService实例注册为IProductService供其他服务使用,可手动创建实例并分别注册:

// 创建第一个实例并注册
var service1 = new ProductService();
services.AddSingleton<IProductService>(service1);
services.AddSingleton<IHostedService>(service1);

// 创建第二个实例并注册
var service2 = new ProductService();
services.AddSingleton<IProductService>(service2);
services.AddSingleton<IHostedService>(service2);

注意:直接解析IProductService时会拿到最后注册的实例(service2),若需区分不同实例,建议使用命名服务。

方式三:命名服务区分实例(推荐)

通过AddKeyedSingleton注册命名的IProductService,再绑定到对应的IHostedService,确保每个实例独立且可精准获取:

// 注册第一个命名实例
services.AddKeyedSingleton<IProductService, ProductService>("product-service-1");
services.AddSingleton<IHostedService>(provider => 
    provider.GetRequiredKeyedService<IProductService>("product-service-1"));

// 注册第二个命名实例
services.AddKeyedSingleton<IProductService, ProductService>("product-service-2");
services.AddSingleton<IHostedService>(provider => 
    provider.GetRequiredKeyedService<IProductService>("product-service-2"));

其他服务需要使用特定实例时,可通过[FromKeyedServices("product-service-1")]特性注入对应的IProductService。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 09:25:34