oro*_*edd 11 c# ninject httpcontext async-await
我有一个使用repository(userRepo
)的方法:
public override Task<IdentityResult> CreateLocalUserAsync(IUser user, string password, CancellationToken cancellationToken)
{
var task = new Task<IdentityResult>(() => {
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;
}
Run Code Online (Sandbox Code Playgroud)
该userRepo
对象具有使用的依赖项HttpContext.Current
.这两个都是使用ninject解决的InRequestScope
.
AccountController
在Mvc 5中默认调用上面的方法:
var result = await IdentityManager.Users.CreateLocalUserAsync(user, model.Password);
Run Code Online (Sandbox Code Playgroud)
我尝试将此设置添加到web.config:
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
Run Code Online (Sandbox Code Playgroud)
另外,我肯定使用的是.NET 4.5.这也在我的web.config中:
<httpRuntime targetFramework="4.5" />
Run Code Online (Sandbox Code Playgroud)
HttpContext
在我开始执行任务之前无法获取信息,因为任务中的依赖userRepo
项正在使用信息,并且使用Ninject解析了这两个对象.
我怎样才能确保HttpContext.Current
不会为空?
Mar*_*ell 16
这里的"任务友好同步上下文"适用于以下内容的延续await
:无论您使用什么result
,它都将具有http上下文.它并没有,但是,涉及到task.Start
.这涉及到TaskScheduler
,而不是同步上下文.
基本上,通过在工作者上执行此操作,您(在此过程中)将该工作者与http上下文分离.你必须:
就我个人而言,我怀疑你是通过将其推向一个工人而获得的.如果你真的想去async
,理想的是你的回购内部支持*Async
方法.这需要的不仅仅是使用线程:它通常意味着架构更改,例如,使用异步SQL方法.从头开始编写使用async
和同步上下文感知连续(aka await
)的东西会自动保存像http上下文之类的东西.
这里的重要区别是async
/ await
实现是线性的但不是连续的,即
<===(work)==>
<===(callback; more work)===>
<===(another callback)===>
Run Code Online (Sandbox Code Playgroud)
where - 因为您现有的代码可能并行执行,即
<==========(original work)=================>
<===========(task on worker thread)=============>
Run Code Online (Sandbox Code Playgroud)
async
/ await
approach 基本上是线性的这一事实使它更适合访问像http-context这样的东西,因为它知道(完成正确)一次只有一个线程访问它 - 即使它不是相同的线程端到端.