从asp.net core 2.1中的控制器访问BackgroundService

Posted

技术标签:

【中文标题】从asp.net core 2.1中的控制器访问BackgroundService【英文标题】:access BackgroundService from controller in asp.net core 2.1 【发布时间】: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() 的实例 【参考方案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 到控制器方法(端点)来完成。

【讨论】:

以上是关于从asp.net core 2.1中的控制器访问BackgroundService的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core 2.1 中的数据保护仅适用于一台机器

如何使用 fetch 将 FormData 从 javascript 发送到 ASP.NET Core 2.1 Web API

ReactJS/ASP.Net Core 2.1 版本 CORS 错误

Angular / ASP.NET Core 2.1 CORS 问题

Asp.net Core WebAPI 基于资源的控制器级别之外的授权

ASP.NET Core 访问控制器构造函数中的 User.Identity