我花了很多时间试图解决这个问题,但我认为我错过了一些东西。这是关于 .NET Core 6/8 和 ASP.Net 管道;故障出在 DI 的范围上,非常感谢任何帮助:
主要有 3 名玩家参与了这次(错误的)互动;在启动序列(Program.cs)中:
serviceCollection.AddScoped(sp => new DatabaseContext(configuration)); //configuration is a value type for r.t. params
serviceCollection.AddScoped<IValidationStep,ConcreteValidatorOne>();
serviceCollection.AddScoped<IValidationStep,ConcreteValidatorTwo>();
. . .
serviceCollection.AddScoped<IValidationGovernor,ValidationGovernor>();
serviceCollection.AddHostedService<UploadStagingService>();
现在,就依赖关系而言:
IEnumerable<IValidationStep>
集合:构造函数 DI-ed我希望下面代码中的所有迭代都能顺利执行;但是,所有依赖项均已正确解析,但 DatabaseContext 除外,该数据库错误会出现“无法访问已处置的上下文实例”错误:
public class UploadStagingService : BackgroundService
{
private readonly ILogger<UploadStagingService> _logger;
private readonly UploadProcessingQueue _uploadProcessingQueue;
private readonly IServiceScopeFactory _scopeFactory;
public UploadStagingService(ILogger<UploadStagingService> logger, UploadProcessingQueue boundedMessageChannel, IServiceScopeFactory scopeFactory)
{
_logger = logger;
_fileProcessingQueue = boundedMessageChannel;
_scopeFactory = scopeFactory;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
await using var _asyncServiceScope = _scopeFactory.CreateAsyncScope();
await foreach (var uploadEntry in _fileProcessingQueue.ReadAllAsync().WithCancellation(stoppingToken))
{
var dbContext = _asyncServiceScope.ServiceProvider.GetRequiredService<DatabaseContext>();
var validators = _asyncServiceScope.ServiceProvider.GetServices<IValidationStep>();
var governor = _asyncServiceScope.ServiceProvider.GetService<IValidationGovernor>();
try
{
_ = Task.Factory.StartNew(() => governor.Complete(uploadEntry));
}
catch (Exception ex) {
...
}
}
}
catch (OperationCanceledException) { _logger.LogDebug("whatever"); }
catch (Exception ex) { _logger.LogError(ex, "..."); }
finally
{
_logger.LogCritical("Fatal Error! Closing the Upload-processing Channel. This service instance should be recycled !");
_uploadProcessingQueue.TryCompleteWriter();
}
}
}
您遇到此问题是因为未正确使用示波器;它应该为每个工作单元创建和处置,而不是在
ExecuteAsync
方法的生命周期内创建和处置。
要解决此问题,您可以尝试修改代码,如下所示:
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
await foreach (var uploadEntry in _uploadProcessingQueue.ReadAllAsync().WithCancellation(stoppingToken))
{
using var scope = _scopeFactory.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<DatabaseContext>();
var validators = scope.ServiceProvider.GetServices<IValidationStep>();
var governor = scope.ServiceProvider.GetRequiredService<IValidationGovernor>();
var task = Task.Run(() => governor.Complete(uploadEntry, dbContext, validators), stoppingToken);
try
{
await task;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing uploadEntry: {uploadEntry}", uploadEntry);
}
}
}
catch (OperationCanceledException)
{
_logger.LogDebug("Upload processing cancelled.");
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in ExecuteAsync of UploadStagingService.");
}
finally
{
_logger.LogCritical("Upload-processing channel is being completed. This service instance should be recycled!");
_uploadProcessingQueue.TryCompleteWriter();
}
}