Hangfire:注入作用域服务的运行方法

问题描述 投票:0回答:1

我在 web-api 控制器操作中排队 Hangfire 作业,但我需要为任务注入服务。

这是代码:

[HttpPost]
public string DoSomething() => _backgroundJobClient.Enqueue<MyStorageService>(s => EnqueueJob(s));

[JobDisplayName("My job"), DisableConcurrentExecution(10 * 60)]
private static async void EnqueueJob(MyStorageService myservice)
{
    await myservice.DoAsync();
}

但是,

MyStorageService
似乎捕获了一些缺失的上下文,因为我得到以下异常。

fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
      An unhandled exception has occurred while executing the request.
      System.InvalidOperationException: variable 's' of type 'MyStorageService' referenced from scope '', but it is not defined
         at System.Linq.Expressions.Compiler.VariableBinder.Reference(ParameterExpression node, VariableStorageKind storage)
         at System.Linq.Expressions.Compiler.VariableBinder.VisitParameter(ParameterExpression node)
         at System.Linq.Expressions.UnaryExpression.Accept(ExpressionVisitor visitor)
         at System.Linq.Expressions.ExpressionVisitor.Visit(ReadOnlyCollection`1 nodes)
         at System.Linq.Expressions.Compiler.VariableBinder.VisitLambda[T](Expression`1 node)
         at System.Linq.Expressions.Compiler.LambdaCompiler.Compile(LambdaExpression lambda)
         at System.Linq.Expressions.Expression`1.Compile()
         at Hangfire.Common.ExpressionUtil.CachedExpressionCompiler.Compiler`2.<>c__DisplayClass7_0.<CompileFromFingerprint>b__0(ExpressionFingerprintChain _)
         at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
         at Hangfire.Common.ExpressionUtil.CachedExpressionCompiler.Compiler`2.CompileFromFingerprint(Expression`1 expr)
         at Hangfire.Common.ExpressionUtil.CachedExpressionCompiler.Compiler`2.Compile(Expression`1 expr)
         at Hangfire.Common.ExpressionUtil.CachedExpressionCompiler.Process[TModel,TValue](Expression`1 lambdaExpression)
         at Hangfire.Common.CachedExpressionCompiler.Wrap(Expression arg)
         at Hangfire.Common.CachedExpressionCompiler.Evaluate(Expression arg)
         at Hangfire.Common.Job.GetExpressionValue(Expression expression)
         at System.Linq.Enumerable.SelectIListIterator`2.ToArray()

MyStorageService
使用 Entity Framework / DbContext 来运行查询。

更新一:

MyStorageService
被添加为
program.cs
中的范围服务:

builder.Services.AddScoped<MyStorageService>();

更新二:

我尝试将 .net 7 文档应用于我的服务: https://learn.microsoft.com/en-us/dotnet/core/extensions/scoped-service

注入

IServiceProvider serviceProvider
以显式创建范围。这会将代码更改为:

[HttpPost]
public string ImportAsync()
{
    using var scope = _serviceProvider.CreateScope();
    var scopedProcessingService = scope.ServiceProvider.GetRequiredService<MyStorageService>();
    return _backgroundJobClient.Enqueue(() => EnqueueJob(scopedProcessingService));
}

[JobDisplayName("My job"), DisableConcurrentExecution(10 * 60)]
public static async Task EnqueueJob(MyStorageService myservice)
{
    await myservice.DoAsync();
}

这允许现在调用

DoAsync()
方法,但是一些依赖项似乎没有被注入到 MyStorageService 内部,因为一些对象现在(仅在这种情况下)
not set to an instance of an object
.

错误:

Failed to process the job '3': an exception occurred. Retry attempt 1 of 10 will be performed in 00:00:44.
System.NullReferenceException: Object reference not set to an instance of an object.
at ..MyStorageService.DoAsync() in ..\MyStorageService.cs:line 52
at ..MyController.Enqueue(MyStorageService myservice) in ..MyController.cs:line 67
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
warn: Hangfire.AutomaticRetryAttribute[0]
...
c# dependency-injection hangfire
1个回答
0
投票

Hangfire 中的依赖注入只对方法调用的目标有效。 你应该像这样重构你的代码:

[HttpPost]
public string DoSomething() => _backgroundJobClient.Enqueue<MyStorageService>(s => s.EnqueueJob());

其中

EnqueueJob
是类
MyStorageService
的实例方法。 (避免使用
async void
方法

[JobDisplayName("My job"), DisableConcurrentExecution(10 * 60)]
public async Task EnqueueJob()
{
    await this.DoAsync();
}
© www.soinside.com 2019 - 2024. All rights reserved.