异步任务中的HttpContext.Current null
我有一个使用存储库( userRepo
)的方法:
public override Task CreateLocalUserAsync(IUser user, string password, CancellationToken cancellationToken) { var task = new Task(() => { TUserEntity newUser = new TUserEntity { Id = user.Id, UserName = user.UserName, Password = password }; userRepo.Save(newUser).Flush(); return new IdentityResult(true); }, cancellationToken); task.Start(); return task; }
userRepo
对象具有使用HttpContext.Current
的依赖项。 使用ninject InRequestScope
解决了这两个问题。
在Mvc 5中的默认AccountController
中调用上面的方法:
var result = await IdentityManager.Users.CreateLocalUserAsync(user, model.Password);
我尝试将此设置添加到web.config:
另外,我肯定使用的是.NET 4.5。 这也在我的web.config中:
在启动任务之前无法从HttpContext
获取信息,因为userRepo
在任务中的依赖关系是使用信息,并且使用Ninject解析了这两个对象。
如何确保HttpContext.Current
不为null?
这里的“任务友好同步上下文”适用于await
的延续:无论你对result
做什么,它都将具有http上下文。 但是,它与task.Start
。 这与TaskScheduler
,而不是sync-context。
基本上,通过对工作人员执行此操作,您(在此过程中)将该工作人员与http上下文分离。 你必须:
- 从http-context获取所需的信息并将其传递给worker,或者
- 不要使用工人
就个人而言,我怀疑你是通过将其推向一个工人而获得的。 如果你真的想要async
,理想的情况是你的repo内部支持*Async
方法。 这需要的不仅仅是使用线程:它通常意味着架构更改,例如,使用异步SQL方法。 从头开始编写使用async
和同步上下文感知延续(也就是await
)的东西会自动保存像http上下文之类的东西。
这里的重要区别是async
/ await
实现是线性的但不是连续的,即
<===(work)==> <===(callback; more work)===> <===(another callback)===>
where – 因为您现有的代码可能并行执行,即
<==========(original work)=================> <===========(task on worker thread)=============>
async
/ await
方法基本上是线性的,这使得它更适合访问像http-context这样的东西,因为它知道(完成正确)一次只有一个线程访问它 – 即使它不是’相同的线程端到端。