【问题标题】:access BackgroundService from controller in asp.net core 2.1从asp.net core 2.1中的控制器访问BackgroundService
【发布时间】:2018-09-07 04:38:06
【问题描述】:

我只需要从控制器访问我的 BackgroundService。 由于 BackgroundServices 被注入了

services.AddSingleton<IHostedService, MyBackgroundService>()

如何从 Controller 类中使用它?

【问题讨论】:

  • 将构造函数添加到控制器public ControllerName(IHostedService service){ .. } 在这里提问之前您是否尝试过阅读文档? docs.microsoft.com/en-us/aspnet/core/fundamentals/…
  • 是的,我做到了。我需要在我的控制器中注入 BackgroundService,而不是 IHostedService 接口。我可以拥有多个 BackgroundService,并且都作为 services.AddSingleton() 注入
  • 需要非常小心的是 aspnet 将 HostedServices 注册为 transient 实例。因此,每当您收到一个实例时,它不是在其上调用了 Start() 的实例

标签: c# asp.net-core asp.net-core-2.1 background-service


【解决方案1】:

最后我在控制器中注入了IEnumerable&lt;IHostedService&gt;,并按类型过滤:background.FirstOrDefault(w =&gt; w.GetType() == typeof(MyBackgroundService)

【讨论】:

    【解决方案2】:

    我就是这样解决的:

    public interface IHostedServiceAccessor<T> where T : IHostedService
    {
      T Service { get; }
    }
    
    public class HostedServiceAccessor<T> : IHostedServiceAccessor<T>
      where T : IHostedService
    {
      public HostedServiceAccessor(IEnumerable<IHostedService> hostedServices)
      {
        foreach (var service in hostedServices) {
          if (service is T match) {
            Service = match;
            break;
          }
        }
      }
    
      public T Service { get; }
    }
    

    然后在Startup:

    services.AddTransient<IHostedServiceAccessor<MyBackgroundService>, HostedServiceAccessor<MyBackgroundService>>();
    

    在我的班级需要访问后台服务...

    public class MyClass
    {
      private readonly MyBackgroundService _service;
    
      public MyClass(IHostedServiceAccessor<MyBackgroundService> accessor)
      {
        _service = accessor.Service ?? throw new ArgumentNullException(nameof(accessor));
      }
    }
    

    【讨论】:

    • 一句警告——在遇到一些异常行为后,请注意虽然 IHostedService 实现的行为类似于单例,但它的状态将无法访问。例如,如果您将private readonly Guid _id = Guid.NewGuid(); 添加到服务类中,并在服务启动与通过 IHostedServiceAccessor 获取时观察它,您会注意到它是两个不同的值。
    • @UtopiaLtd 不要将后台服务添加为Transient,而是添加为Singleton。 microsoft 文档指出托管服务必须自己创建范围,就像您将其添加为 Scoped 一样,您可能会使用已处置的对象。
    • 从 .NET 5.0 开始,API 派生自 ControllerBase。如果这个答案解决了从 ControllerBase 派生的“MyController”如何调用 BackgroundService 会更好。
    【解决方案3】:

    在ConfigureServices函数中添加BackgroundService:

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddHostedService<ListenerService>();
    
    
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }
    

    在控制器中注入:

    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        private readonly IHostedService listenerService;
    
        public ValuesController(IHostedService listenerService)
        {
            this.listenerService = listenerService;
        }
    }
    

    我使用 BackgroundService 为 AWSSQS 侦听器启动了多个侦听器。如果消费者想要旋转新的监听器,那么可以通过 POST 到控制器方法(端点)来完成。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-12
      • 2020-04-05
      • 1970-01-01
      • 1970-01-01
      • 2022-12-29
      • 1970-01-01
      • 1970-01-01
      • 2019-02-11
      相关资源
      最近更新 更多