其实核心逻辑和同步释放是一致的 , 只是IAsyncDisposable
接口中的DisposeAsync()
方法返回的异步相关的ValueTask所以需要进行一些等待相关的操作 。不过本质都是循环释放_disposables
里的数据,而这些数据正是当前作用域里里实现了IDisposable或IAsyncDisposable接口的实例 。
使用群友问题解答关于CreateScope()
或GetService()
方法的时候,都会判断当前作用域是否释放,而这个标识正是在Dispose()
或DisposeAsync()
置为true
的 。我们上面文章中的那个异常的引发点也正是这里 , 也正是因为作用域被释放了表示为置为true
了,所以GetService才会直接抛出异常 。
ServiceProviderEngineScope
重要的相关实现,咱们上面已经大致的讲解过了 。其实探索它的原动力就是因为群友遇到的一些关于这方面的疑问,如果了解了它的实现的话便能轻松的解除心中的疑问 , 还原一下当时有疑问的代码IServiceCollection services = new ServiceCollection();services.AddScoped<Person>(provider => new() { Id = 1, Name = "yi念之间", Sex = "Man" });IServiceProvider serviceProvider = services.BuildServiceProvider();Person person = null;using (IServiceScope serviceScope = serviceProvider.CreateScope()){ person = serviceScope.ServiceProvider.GetService<Person>(); Console.WriteLine(person.Name);}if (person == null){ Console.WriteLine("Person被回收了");}【细聊.Net Core中IServiceScope的工作方式】代码大致描述的就是当时的这么一个场景,这里毫无疑问哈,完全判断不出来Person是否已经被回收 。通过上面的源码咱们就可以知道 , 无论是掉用
ServiceProviderEngineScope
的是Dispose()
或DisposeAsync()
方法(using上面咱们说过了就是语法糖),其实都是调用了当前作用域内实现了IDisposable
或IAsyncDisposable
接口的实例里的Dispose()
或DisposeAsync()
方法 。- 即使当前实例实现了
IDisposable
或IAsyncDisposable
接口,且调用了实例内的Dispose()
或DisposeAsync()
方法,也不意味着当前对象已经被释放了,因为我们用Dispose方法里多半是这个对象里引用的非托管代码的释放工作,并不意味这当前对象被释放了 。
IServiceScope
实现类ServiceProviderEngineScope
里ResolvedServices属性享元的实例,也就是生命周期为ServiceLifetime.Scoped
的实例 。这些实例何时被回收是取决于两点 , 一是当前实例的访问是否超出当前作用域,二是当前对象是否有被引用 。上面的示例中IServiceScope
实例虽然已经超出作用了(因为在using括号之外了),但是Person外出的栈里还引用着ResolvedServices字典里Person对象的实例,所以GC
即垃圾回收机制并不会回收这个实例,因为它还在被引用 。那就意味着它不能被释放,也就不存在Person实例被回收这么一说了 。
GC
来负责的 。细想一下就会明白了 , 托管对象的回收本身就是垃圾回收处理的,就和你自己写单例模式或者直接new一个对象实例的时候,你也没考虑对象的回收问题,因为垃圾回收机制已经帮你处理了 。总结在.Net Core体系中IOC一直是核心模块 , 且关于Scope的作用域的问题,一直会有人产生疑问,想更深刻的了解一下还是得多拿一些时间研究一下 。有些知识不是靠一时半会的学就能牢牢地掌握,需要日常不断的积累和不断的解决问题,才能掌握的更多 。因为设计到的源码比较多,而且不熟悉的话可能不是很好理解,所以还需要平时的积累,积累的越多能解决的问题越多,才能避免入坑 。好了大致总结一下
- 当我们使用
CreateScope()
或CreateAsyncScope()
创建出ServiceProviderEngineScope
或AsyncServiceScope
推荐阅读
- asp.net core web 解决方案多项目模板制作打包总结
- ubuntu-22.04 树莓派Zero 2 W通过.NET6和libusb操作USB读写
- 上 学习ASP.NET Core Blazor编程系列六——新增图书
- Azure DevOps Pipelines部署.Net Core 应用到Kubernetes
- C语言小白刷题
- 记一次 .NET 某企业OA后端服务 卡死分析
- .NET 采用 SkiaSharp 生成二维码和图形验证码及图片进行指定区域截取方法实现
- .Net CLR异常简析
- 记一次 .NET 某电子病历 CPU 爆高分析
- .NET 7 RC 2 发布,倒计时一个月发布正式版