记一次EF Core DBContext在Action委托中GC异常的问题.
今天在开发过程中发现.在SaveChanges的时候偶尔会抛出异常: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.
异常说得很明显,通过依赖注入的DBContext上下文已经被其他地方Dispose了.所以无法再次Dispose.


代码逻辑很简单,就是发送邮件后,调用委托通知tracking发送成功.然后保存到数据库.
按理说这段代码没问题,但就是报错了.
一开始以为是哪里没有await,所以导致task开的新线程没有被等待,从而导致提前gc.但代码就这么多,都检查过了没有遗漏的地方.排除
后来怀疑是DBContext的生命周期问题,但DBcontext是ServiceLifetime.Scoped. 同一个request中是单例的.排除
后来经过和同事交流,在代码结尾处加入Task.CompletedTask.等待所有线程结束.

神奇的事情发生了,完美运行.不报错了.
那这样的话,就问题就只可能是定义的Action<int> rollBack委托的问题了.

猛然发现,尽管我在代码中确实加入了async/await关键字

但是这里的异步等待,只是异步等待委托内部的操作.并不等待Action委托本身.也就是说,当我们执行委托里的方法时.开辟了一个新的线程去执行_dbContext.SaveChangesAsync()的方法.但是并没有等待它完成.
这时候主线程会立即执行下一步,也就是返回结果给Controller层. Return Ok()给前端.这个时候DBContex立刻就会调用Dispose.等到委托的方法调用完毕再次Dispose的时候.自然而然的就会抛出异常啦.因为他之前已经被Dispose了.
所有解决办法很简单
方法一 在代码结尾加入await Task.CompletedTask 等待所有线程都结束.再返回.
方法二 讲Action<int> 换成 Func<int,Task> 并在调用委托前 await
经过这次问题,还是暴露出不少问题.
1:对async/await 还是有认识不足的地方.基础知识不扎实,导致了对委托的错误使用.
2:对自己的代码太过自信.没有做完整的测试.事实上 这里的代码我都没测试过就上了DEV环境.认为很简单不会出问题的.做事还是太浮躁.
所以写一篇博客,用以自省
记一次EF Core DBContext在Action委托中GC异常的问题.的更多相关文章
- EF Core使用CodeFirst在MySql中创建新数据库以及已有的Mysql数据库如何使用DB First生成域模型
官方教程:https://docs.microsoft.com/en-us/aspnet/core/data/?view=aspnetcore-2.1 使用EF CodeFirst在MySql中创建新 ...
- [翻译 EF Core in Action 2.2] 创建应用程序的数据库上下文
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
- EF Core in Action 中文翻译 第一部分导航
Entityframework Core in action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Core ...
- [翻译 EF Core in Action 2.1] 设置一个图书销售网站的场景
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
- [翻译 EF Core in Action 2.0] 查询数据库
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
- [翻译 EF Core in Action 1.9] 掀开EF Core的引擎盖看看EF Core内部是如何工作的
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
- [翻译 EF Core in Action 1.8] MyFirstEfCoreApp应用程序设置
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
- [翻译 EF Core in Action 1.7] MyFirstEfCoreApp访问的数据库
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
- [翻译] EF Core in Action 关于这本书
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
随机推荐
- Visual Studio Code安装Python环境
如何在全宇宙最强编辑器安装Python运行环境 (雾 首先安装Python2和Python3,如果只需要用到一个的话,直接安装即可运行,不存在转换问题. 安装Python扩展,直接搜索安装即可. 更改 ...
- MYSQL之查询篇
2. 数据库操作 数据库在创建以后最常见的操作便是查询 2.1 查询 为了便于学习和理解,我们预先准备了两个表分别是stduents表和classes表两个表的内容和结构如下所示 students表的 ...
- Spring boot 自定义banner的在线制作
目前工作不是很忙,利用闲暇的时间,在给自己不断地充电,提升自己的技术实力. 目前在做一个基于Spring Boot2.x+webmagic+quartz的爬虫项目[hotDog]https://git ...
- [Advanced Python] 14 - "Generator": calculating prime
高性能编程 几个核心问题 • 生成器是怎样节约内存的?• 使用生成器的最佳时机是什么?• 我如何使用 itertools 来创建复杂的生成器工作流?• 延迟估值何时有益,何时无益? From: htt ...
- C++基础之顺序容器
顺序容器简介: 顺序容器类型 描述 vector 可变大小数组,支持快速访问,在尾部之外的地方插入或删除时可能很慢 deque 双端队列.支持快速访问,在头尾插入删除会很快. list 双向列表.只支 ...
- 一起看期待已久的.NET Core 3.0新的单文件部署特性,记在昨日VS2019更新后
VS2019又又又迎来一次新的更新,这次的重点在.NET Core, 妥妥的更新好,默默地反选2.2,一切都在意料之中. 这次我们来看VS2019的新特性单文件部署: https://www.talk ...
- 【面试题】Java常见面试题
集合与数组? 数组:(可以存储基本数据类型)是用来存储对象的一种容器,但是数组的长度固定,不适合在对象数量未知的情况下使用 集合:(只能存储对象,对象类型可以不一样)集合的长度可变,可在多数情况下使用 ...
- Spring常犯的十大错误,你踩过吗?
1.错误一:太过关注底层 我们正在解决这个常见错误,是因为 "非我所创" 综合症在软件开发领域很是常见.症状包括经常重写一些常见的代码,很多开发人员都有这种症状. 虽然理解特定库的 ...
- 如何优雅的使用springboot项目内置tomcat
问题:以前,我们在使用SSM框架的时候,都是通过外置的tomcat进行部署,如果想访问文件,直接拖到项目的根目录下面即可.假如我们需要放一个apk文件,然后让别人下载,只需将apk放到项目根目录下面, ...
- layer.open打开一个新的jsp页面,如何关闭并刷新父页面问题
layer.open打开一个新的jsp页面弹框,如何关闭呢? 在新的页面提交完毕之后,关闭并刷新父页面列表. layer.closeAll(); parent.layer.closeAll(); wi ...