ASP.Net WebForms中DryIOC结合Task.Run()的作用域兼容问题求助
解决ASP.NET WebForms中DryIoc跨线程作用域问题
核心问题原因
DryIoc的HttpContextScopeContext仅绑定当前Web请求的HttpContext,而Task.Run启动的后台线程没有HttpContext;ThreadScopeContext又和Web请求的线程绑定死,导致两种场景下的作用域无法互通,解析服务时就会触发NoCurrentScope错误。
解决方案步骤
1. 实现混合作用域上下文
自定义一个IScopeContext,让它优先从HttpContext获取作用域,无HttpContext时再从线程上下文读取:
public class HybridScopeContext : IScopeContext { private readonly IScopeContext _httpContextScope = new HttpContextScopeContext(); private readonly IScopeContext _threadScope = new ThreadScopeContext(); public IScope GetCurrentScope() { // Web请求场景优先使用HttpContext中的作用域 var httpScope = _httpContextScope.GetCurrentScope(); if (httpScope != null) return httpScope; // 后台线程场景使用线程上下文的作用域 return _threadScope.GetCurrentScope(); } public void SetCurrentScope(IScope scope) { // 存在HttpContext则绑定到HttpContext,否则绑定到当前线程 if (HttpContext.Current != null) _httpContextScope.SetCurrentScope(scope); else _threadScope.SetCurrentScope(scope); } }
2. 初始化容器时替换默认上下文
创建容器时指定使用自定义的混合作用域上下文:
var container = new Container(rules => rules .WithDefaultReuse(Reuse.Scoped) .WithScopeContext<HybridScopeContext>());
3. 后台线程中手动绑定作用域
在Task.Run执行代码时,需手动开启作用域并绑定到当前线程,确保服务解析时能找到上下文:
Task.Run(() => { using (var scope = container.OpenScope()) { var scopeContext = container.ScopeContext as HybridScopeContext; scopeContext?.SetCurrentScope(scope); // 在此处解析并使用服务 var service = scope.Resolve<IScopedService>(); service.DoWork(); } });
4. 为HttpHandler添加作用域支持
普通HttpHandler不会自动创建作用域,写一个基类统一处理:
public abstract class BaseHttpHandler : IHttpHandler { protected readonly IContainer _container; protected BaseHttpHandler(IContainer container) { _container = container; } public bool IsReusable => false; public void ProcessRequest(HttpContext context) { using (var scope = _container.OpenScope()) { var scopeContext = _container.ScopeContext as HybridScopeContext; scopeContext?.SetCurrentScope(scope); ProcessRequestWithContext(context, scope); } } protected abstract void ProcessRequestWithContext(HttpContext context, IScope scope); }
后续所有HttpHandler都继承这个基类,在ProcessRequestWithContext方法中解析服务即可。
5. 验证作用域隔离
测试Web请求和后台线程中的Scoped服务是否为独立实例,避免跨上下文共享实例的问题。
内容的提问来源于stack exchange,提问作者Massoud Safari
相关产品推荐
相关产品推荐

