ASP.NET Core 新建线程中使用依赖注入的问题

栏目: ASP.NET · 发布时间: 6年前

内容简介:问题来自博问的一个提问TCPService 通过构造函数注入了 ContentService , ContentService 的实例依赖了 AppDbContext (继承自 EF Core 的 DbContext)。在 TCPService 中通过 Thread.Start 启动了一个新的线程执行了 TCPService 中的 Receive 方法,在 Receive 方法中通过 ContentService 进行保存数据库的操作,而在访问 AppDbContext 的实例时出现对象已被 Dispos

问题来自博问的一个提问 .net core 多线程数据保存的时候DbContext被释放

TCPService 通过构造函数注入了 ContentService , ContentService 的实例依赖了 AppDbContext (继承自 EF Core 的 DbContext)。在 TCPService 中通过 Thread.Start 启动了一个新的线程执行了 TCPService 中的 Receive 方法,在 Receive 方法中通过 ContentService 进行保存数据库的操作,而在访问 AppDbContext 的实例时出现对象已被 Disposed 的错误。

Object name: 'AppDbContext'. --->System.ObjectDisposedException: Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.

针对这个问题,尝试改为通过构造函数注入 IServiceProvider ,在 TCPService.Receive (在新线程中执行的方法)中通过 IServiceScope 解析

using (var scope = _serviceProvider.CreateScope())
{
    var contentService = scope.ServiceProvider.GetRequiredService<ContentService>();
    //...
}

结果发现 IServiceProvider 也被 Disposed

System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'IServiceProvider'.

由此可以推断在 ASP.NET Core 中在新建的线程中无法通过依赖注入的方式访问实现了 IDisposable 接口的对象(单例对象除外,但实现 IDisposable 接口的类型通常不会注册为单例),也就是只要请求一结束,实现 IDisposable 接口的对象的 Dispose 方法就会被调用。

那如何解决这个问题呢?

1)最下下策的解决方法是将 DbContext 注册为单例

services.AddDbContext<AppDbContext>(options => { }, ServiceLifetime.Singleton);

它会带来很多副作用,不考虑。

2)在保存数据至数据库的实现方法中基于 DbContextOptions (它是单例)手工 new AppDbContext ,用这个 DbContext 实例进行保存操作。

public class ContentService : Repository<Content>
{
    private readonly DbContextOptions _options;

    public ContentService(AppDbContext Context, DbContextOptions options) : base(Context)
    {
        _options = options;
    }

    public override async Task<bool> SaveAsync(Content entity)
    {
        using (var context = new AppDbContext(_options))
        {
            context.Set<Content>().Add(entity);
            return await context.SaveChangesAsync() > 0;           
        }
    }
}

实测有效。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

硅谷之火

硅谷之火

保罗·弗赖伯格、迈克尔·斯韦因 / 张华伟 编译 / 中国华侨出版社 / 2014-11-1 / CNY 39.80

《硅谷之火:人与计算机的未来》以生动的故事,介绍了计算机爱好者以怎样的创新精神和不懈的努力,将计算机技术的力量包装在一个小巧玲珑的机壳里,实现了个人拥有计算机的梦想。同时以独特的视角讲述了苹果、微软、太阳微系统、网景、莲花以及甲骨文等公司的创业者们在实现个人计算机梦想的过程中创业的艰辛、守业的艰难、失败的痛苦,在激烈竞争的环境中奋斗的精神以及在技术上不断前进的历程。一起来看看 《硅谷之火》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具