任务中的Principal.Identity.Name从Controller Action运行

时间:2014-09-22 20:03:38

标签: asp.net-mvc task-parallel-library ninject task

在控制器操作中我正在运行

public ActionResult MyAction()
{
    Task.Factory.StartNew( () =>
    {
        myService.ExecuteMethod( someArgs );
    } );
}

该服务将调用调用其他类的其他类方法,并且在某个地方,IPrincipal被注入到类的构造函数中。

IPrincipal是通过HttpContext.Current.User创建的。

由于代码位于Task,因此它在不同的线程上运行,并且操作已返回,因此HttpContext.Currentnull

如果我尝试Thread.CurrentPrincipal,它就存在,但设置为HttpContext.Current.User以外的其他内容。此外,如果我尝试访问Thread.CurrentPrincipal.Identity.Name,我会抛出ObjectDisposedException

我使用Ninject作为我的IoC容器。 IPrincipal绑定看起来像这样

Bind<IPrincipal>().ToMethod( x => HttpContext.Current.User );

是否有办法在控制器操作中从IPrincipal运行代码中获取正确甚至可用的Task

1 个答案:

答案 0 :(得分:0)

HttpContext.Current.User基本上类似于临时ThreadLocal。因此,在开始在不同线程中运行的任务之前,您需要检索它的值。无法找出哪个帖子已执行Task.Factory.StartNew并检索了它的ThreadLocal值。 考虑一下,一旦你Task.Factory.StartNew,webrequest甚至可以在任务实际开始之前结束。 所以你需要做的是:

IPrincipal principal = HttpContext.Current.User;

Task.Factory.StartNew( () =>
{
    myService.ExecuteMethod(principal);
} );

现在,如果将IPrincipal(ctor-)注入myService ,则 myService会根据请求进行实例化.InTransientScope(),{{1您的当前绑定将起作用,因为控制器是针对每个请求实例化的(另请参阅lifecycle of an asp.net mvc5 application)。

问题只会在注入.InRequestScope()或执行Lazy<IPrincipal>时出现(这包括使用ninject.extensions.factory,如IResolutionRoot.Get<IPrincipal>!),因为此时{{1}可能不再有效。

我建议如果您希望答案更准确,更重要,您需要发布Minimal, Complete, and Verifiable example