问题 异步任务中的HttpContext.Current null


我有一个使用存储库的方法(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;
    }

userRepoobject具有使用的依赖项 HttpContext.Current。这两个都是使用ninject解决的 InRequestScope

在默认情况下调用上述方法 AccountController 在Mvc 5中:

var result = await IdentityManager.Users.CreateLocalUserAsync(user, model.Password);

我尝试将此设置添加到web.config:

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />

另外,我肯定使用的是.NET 4.5。这也在我的web.config中:

<httpRuntime targetFramework="4.5" />

无法从中获取信息 HttpContext 在我开始任务之前因为依赖性 userRepo 在任务中使用信息,并使用Ninject解析两个对象。

我怎样才能确保这一点 HttpContext.Current 不会是空的吗?


5088
2017-10-01 08:17


起源

“我怎么能确保这一点 HttpContext.Current 不会是空的吗?“不要使用 Tasks或 async - await 一点都不在这种情况下,它没有改善任何东西。 - svick
@svick好吧, await 至少可以识别http-context;这里的问题是 Task.Start 不是。 - Marc Gravell♦
链接: stackoverflow.com/questions/18383923/... - Cuong Le


答案:


这里的“任务友好同步上下文”适用于从中继续 await:无论你做什么 result,它将具有http上下文。确实如此 然而,与...有关 task.Start。这涉及到 TaskScheduler,而不是同步上下文。

基本上,通过对工作人员执行此操作,您(在此过程中)将该工作人员与http上下文分离。你必须:

  • 从http-context获取您需要的信息并传递它  工人,或
  • 不要使用工人

就个人而言,我怀疑你是通过将其推向一个工人而获得的。如果你真的想去 async,理想的是你的回购内部支持 *Async 方法。这需要的不仅仅是使用线程:它通常意味着架构更改,例如,使用异步SQL方法。从头开始写的东西用 async 和同步上下文感知延续(又名 await)会自动保存像http上下文之类的东西。

这里的重要区别在于 async/await 实施是线性的但不是连续的,即

 <===(work)==>
                    <===(callback; more work)===>
                                                     <===(another callback)===>

在哪里 - 因为您现有的代码可能执行的任务 在平行下,即

<==========(original work)=================>
         <===========(task on worker thread)=============>

这个事实 async/await 方法是 基本上 线性使它更适合访问像http-context这样的东西,因为它知道(完成正确)一次只有一个线程访问它 - 即使它不是端到端的相同线程。


16
2017-10-01 09:18