.NetCore EFCore 多线程生命周期管理
作者:互联网
1、多线程下EFCore的DbContext实例处理
DbContext生命周期默认注入是Scope,每一次请求时创建一个实例,在当前请求的上下文中共用,当请求结束后,释放生命周期,释放数据库链接。若开启多线程,在不同的线程中使用同一个DbContext上下文,则报错如下:System.InvalidOperationException: A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.代码演示如下:
解决办法: 在GetAsync中重新创建DbContext(new SecondHandDbContext),不使用请求注入的DbContext:
2、多线程下生命周期已被释放
生命周期为Scope方式,随着请求的结束,实例生命周期也会被释放,因此在多线程下若共享实例,容易出现实例已释放的错误,报错如下:Instances cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it (or one of its parent scopes) has already been disposed.Autofac at Autofac.Core.Lifetime.LifetimeScope.BeginLifetimeScope(Object tag)。通过注入IServiceProvider,
解决办法:
1、在构造函数注入IServiceProvider,应用中通过IServiceProvider的GetService方法获取实例,最终发现IServiceProvider也已被释放,IServiceProvider只是当前请求的实例,该方法失败。
2、从当前应用中获取实例,构造函数注入IHost,通过host获取IServiceProvider:
在线程中通过_sp创建新的生命周期:
using (var sp = _sp.CreateScope())
{
await Task.Delay(5000);
var applyReposity = sp.ServiceProvider.GetRequiredService<IApplyReposity>();
Console.WriteLine($"taskCode:{applyReposity.GetHashCode()},taskThreaId:{Thread.CurrentThread.ManagedThreadId}");
var model = await applyReposity.GetAsync(c => 1 == 1);
sp.Dispose();
}
观察curThreaId与taskThreaId,Task.Run开启了新的线程,与当前主线程线程ID不同,当前请求中注入的IApplyReposity的实例_applyReposity编码是57588670,新线程中开启的新生命周期sp.ServiceProvider中获取的实例编码是2837748;主线程与子线程实例不再相关,解决主线程已释放,子线程获取不到实例的问题。
标签:生命周期,NetCore,sp,DbContext,实例,线程,EFCore,IServiceProvider,多线程 来源: https://www.cnblogs.com/zxsn2014/p/16478922.html