使用Hangfire在ASP.NET Core C#中,单例服务被构建多次

5

我正在一个ASP.net core (2.2)应用程序中使用基于内存的Hangfire(1.6.21)。在Startup.cs文件中,我正在将一个服务配置为单例:

services.AddSingleton<IXXXService, XXXService>(); // In ConfigureServices(...)

同时使用以下代码初始化Hangfire:

app.UseHangfireServer(); // In Configure(...)

这里是XXXService简化后的代码:
public class XXXService : IXXXService
{
    public ExternalAPIService()
    {
        Console.WriteLine("xxx");
    }

    public void QueueRequest(Guid requestId)
    {
        BackgroundJob.Enqueue(() => this.AnalyzeRequest(requestId));
    }

    public async Task AnalyzeRequest(Guid requestId)
    {
        Console.WriteLine("Analyzing request...");
    }
}

问题在于,虽然XXXService被定义为单例模式——确实只有通过连续请求才会创建一次,但当最终调用AnalyzeRequest时,它会被Hangfire重新创建。我该如何将Hangfire路由到由ASP默认DI管理的单例对象?

我假设Hangfire为每个后台作业使用自己的服务范围。 - Brad
在你的代码中使用依赖注入并调用静态类是一种非常奇怪的模式,这有点违背了依赖注入的思想。难道你应该使用 IBackgroundJobClient 吗?!文档 明确指出 BackgroundJobIBackgroundJobClient 的一个包装器。 - Tseng
你为什么认为它是在回调函数中重新创建的呢?仔细思考一下,该实例应该被捕获在lambda作用域中。确定没有你省略的代码导致它在其他地方被解析吗? - Tseng
@MaorVeitsman,你解决了吗?我也遇到了同样的问题——Hangfire每次都会为循环任务调用构造函数。 - el vis
@elvis 很抱歉,我已将 critical 属性更改为静态以快速解决问题。 - Maor Veitsman
显示剩余2条评论
2个回答

4
我发现我需要执行以下操作: 首先,我们告诉作业需要使用哪个服务。请注意,在这里我们给出接口。
BackgroundJob.Enqueue<IService>(service => service.Method(param));

根据建议,我们需要在Hangfire使用的JobActivator中添加一个覆盖。Hangfire获取表达式并知道它需要实现IService的服务,因此我们只需告诉它如何获取该服务。

接下来我们需要创建如下的JobActivator:

public class ServiceProviderActivator : JobActivator
{
    private IServiceProvider _serviceProvider;

    public ServiceProviderActivator(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public override object ActivateJob(Type jobType)
    {
        return _serviceProvider.GetService(jobType);
    }
}

现在,当Hangfire尝试运行该作业时,它将需要一个IService,并使用服务提供程序。现在,唯一剩下的就是给它与您的应用程序使用相同的服务提供程序。

在Startup文件的ConfigureServices方法中:

services.AddHangfire((serviceProvider, configuration) =>
{
    // other configuration
    configuration.UseActivator(new ServiceProviderActivator(serviceProvider));
});

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接