记一次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 ...
随机推荐
- StringBulider类
StringBulider类创建的字符串同样可以对字符串进行修改: public class StringBuliderDemo { public static void main(String[] ...
- 读取用户输入并判断的bash脚本
#!/bin/bash echo -e "1) A"echo -e "2) B"echo -e "3) C"echo -e "4) ...
- tcp居然会数据延迟40ms被发送
tcpdump是很好的tcp分析工具,在此配合nc命令来学习tcpdump nc -l 8000 tcpdump -S -n -i lo tcp and host 127.0.0.1 and port ...
- [Pandas] 01 - A guy based on NumPy
主要搞明白NumPy“为什么快”. 学习资源 Panda 中文 易百教程 远程登录Jupyter笔记本 效率进化 四步效率优化 NumPy 底层进行了不错的优化. %timeit 对于任意语句,它会自 ...
- 多事之秋-最近在阿里云上遇到的问题:负载均衡失灵、服务器 CPU 100%、被 DDoS 攻击
昨天 22:00~22:30 左右与 23:30~00:30 左右,有1台服役多年的阿里云负载均衡突然失灵,造成通过这台负载均衡访问博客站点的用户遭遇 502, 503, 504 ,由此给您带来麻烦, ...
- vue中关于滚动条的那点事
vue中关于滚动条的那点事 不知道你有没有遇到过这种情况,有时当页面切换时,滚动条不在页面的顶端.最近半路加入一个项目,就遇到这种情况.(若只是为了解决此问题,可直接翻到最下方)下面谈谈解决此问题的过 ...
- SpringBoot起飞系列-Web开发(四)
一.前言 从今天你开始我们就开始进行我们的web开发,之前的一篇用SpringBoot起飞系列-使用idea搭建环境(二)已经说明了我们如何进行开发,当然这是搭建起步,接下来我们就开始进行详细的开发, ...
- Maven 梳理 - Maven中的dependencyManagement 意义
1.在Maven中dependencyManagement的作用其实相当于一个对所依赖jar包进行版本管理的管理器. 2.pom.xml文件中,jar的版本判断的两种途径 1:如果dependenci ...
- GetThreadTimes获取其它线程cpu时间
http://www.cnblogs.com/eaglet/archive/2009/03/11/1408809.html 鄙视下上面的垃圾博文,纯粹忽悠人 参考文章: http://blog.kal ...
- map转换成com.google.gson.JsonObject
String json =new Gson().toJson(map); JsonObject jsonObject =new JsonParser().parse(json).getAsJsonOb ...