【发布时间】:2022-06-13 20:47:50
【问题描述】:
我正在运行以下后台服务:
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await Task.Run(async () =>
{
while (!stoppingToken.IsCancellationRequested)
{
using (var scope = _scopeFactory.CreateScope())
{
DataContext dbContext = scope.ServiceProvider.GetRequiredService<DataContext>();
var tasks = new List<Task>();
tasks.Add(siteA.ProcessSchedule(SportLeagues.MLB, logger, dbContext));
tasks.Add(siteB.ProcessSchedule(SportLeagues.MLB, logger, dbContext));
//....more of same task
await Task.WhenAll(tasks);
await dbContext.SaveChangesAsync();
await Task.Delay(0, stoppingToken);
}
}
});
}
我经常收到这个错误
System.InvalidOperationException:
A second operation was started on this context instance before a previous operation completed.
我可以重构并为每个任务创建一个dbContext,但是如果可能的话,我更愿意使用单个 dbContext。
我还尝试将我的 dbContext 添加为瞬态:
builder.Services.AddDbContext<DataContext>(options =>
{
options.UseInMemoryDatabase("db");
}, ServiceLifetime.Transient);
但这并没有帮助。我是否以不正确的方式创建了我的 dbContext?或者是为每个任务创建一个新的dbContext 的最佳方法?对于更多上下文,这是一个不断运行的后台任务,需要一秒钟才能完成,它将有大约 20 个任务。每秒创建和销毁 20 个 dbContext 以及必须进行 20 个 dbContext 保存听起来效率很低。
【问题讨论】:
-
如果您连续进行这项工作,您不需要创建和销毁上下文,您可以只保留它们并重新使用它们。是的,每个并行运行的任务都需要一个,它们不是线程安全的。
标签: c# asp.net .net entity-framework asp.net-core