异步任务中HttpContext.Current为空

12

我有一个使用仓库(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;
    }
userRepo 对象具有一个依赖项,该依赖项使用 HttpContext.Current。这两者都使用 ninject 的 InRequestScope 解析。
上述方法在 Mvc 5 的默认 AccountController 中调用:
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" />

由于任务中的userRepo依赖项使用了信息,并且这两个对象都是使用Ninject解析的,因此在开始任务之前无法从HttpContext中获取信息。

我该如何确保HttpContext.Current不会为空?


我该如何确保 HttpContext.Current 不会为空?在这种情况下,不要使用 Taskasync-await,因为它们对此没有任何改进。 - svick
@svick 嗯,await 至少是 http 上下文感知的;这里的问题是 Task.Start 不是。 - Marc Gravell
链接:https://dev59.com/7mMl5IYBdhLWcg3wc2xp为什么在await后HttpContext.Current为空? - cuongle
1个回答

17
这里的“任务友好同步上下文”是指从await继续执行时的上下文:无论您如何使用result,它都将具有http上下文。然而,它与task.Start没有关系,而是与TaskScheduler和同步上下文无关。
基本上,通过在工作线程上执行此操作,您正在将该工作线程与http上下文分离。您必须要么:从http上下文获取所需信息并将其传递给工作线程内部,要么不使用工作线程。
个人认为,将其推到工作线程上不会带来太大的收益。如果您真的想使用async,则理想情况是您的存储库内部支持*Async方法。这不仅需要使用线程,通常还需要进行架构更改,例如使用异步SQL方法。从头开始编写以使用async和同步上下文感知的连续(即await)的内容,可以自动保留诸如http上下文之类的信息。
这里的重要区别在于async/await实现是线性但不是连续的。
 <===(work)==>
                    <===(callback; more work)===>
                                                     <===(another callback)===>

与您现有的代码可能并行执行事情相反,即

<==========(original work)=================>
         <===========(task on worker thread)=============>
async/await方法本质上是线性的,这使得它更适合访问诸如http-context之类的内容,因为(如果做得好)一次只会有一个线程访问它,即使不是同一个线程。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接