将Scoped服务实例传入Singleton后台执行的风险与合规性问询
ASP.NET 6 作用域服务与单例服务交互问题解答
示例代码
public class ScopedB { ScopedA _scopedA; Singleton1 _singleton1; public ServiceB(ScopedA scopedA, Singleton1 singleton1) { _scopedA = scopedA; _singleton1 = singletonA; } public async Task DoSomethingAsync() { await _singleton1.PerformALongerOperationWichNeedsServiceAAsync(_scopedA); } }
问题解答
问题1:请求结束后单例仍使用作用域服务是否会导致失败?该做法可行吗?
- 会导致操作失败,这种做法完全不可行。当HTTP请求结束时,ASP.NET会自动释放该请求作用域内的所有服务实例,包括
ScopedA。如果Singleton1的后台长时间运行方法还在使用ScopedA,此时访问已被释放的实例会直接抛出ObjectDisposedException之类的异常。另外,ScopedA可能依赖其他请求级资源(比如数据库上下文),这些资源也会随请求结束被释放,进一步导致后续操作无法正常执行。
问题2:当前做法是否属于作用域违规?
- 这属于典型的作用域违规。虽然不是直接在单例的构造函数中注入作用域服务,但本质是将请求作用域内的
ScopedA实例传递给了生命周期远长于它的单例服务,让单例持有了作用域服务的引用。这会破坏作用域服务的生命周期管理,导致作用域服务无法在请求结束时被正常释放,还可能引发线程安全问题,和直接在单例中注入作用域服务的违规性质完全一致。
内容的提问来源于stack exchange,提问作者David Mason
相关产品推荐
相关产品推荐

