我正在使用 .AsParallel().ForAll() 在 ASP.NET 请求上下文中并行枚举集合。枚举方法依赖于System.Threading.Thread.CurrentPrincipal。
我是否可以依赖用于将 System.Threading.Thread.CurrentPrincipal 设置为处理 ASP.NET 请求的线程的 HttpContext.Current.User 的各个线程,还是我需要自己进行管理?
提出问题的另一种方式是 PLINQ 使用的线程是否继承调用该操作的线程的标识?
不,身份不会自动传播到这些工作线程。事实上,如果您使用的组件是HttpContext.User
你能做的就是捕捉当前的“环境”HttpContext
在您的“主”线程中实例并将其传播到您的工作线程。那看起来像这样:
HttpContext currentHttpContext = HttpContext.Current;
myWorkItems.AsParallel().ForAll(wi =>
{
HttpContext.Current = currentHttpContext;
try
{
// anything called from here out will find/use the context of your original ASP.NET thread
}
finally
{
// Disassociate the context from the worker thread so that it is not held on to beyond its official lifetime
HttpContext.Current = null;
}
});
这有效是因为HttpContext.Current
由线程静态支持,因此每个工作线程都将从主线程分配实例,并且从该点开始对其执行的任何工作都将将该实例视为当前实例。
现在,你必须意识到HttpContext
及其相关的类并不是被设计为线程安全的,所以这有点像黑客。如果您只读取属性,这并不是真正的问题。如果您不使用依赖于HttpContext.Current
那么不设置它而是使用捕获的数据会更“干净”currentHttpContext
变量直接在worker中。
最后,如果您真正需要的只是将当前主体传播到工作线程,那么您可以使用相同的方法来做到这一点:
Principal logicalPrincipal = Thread.CurrentPrincipal;
myWorkItems.AsParallel().ForAll(wi =>
{
Principal originalWorkerThreadPrincipal = Thread.CurrentPrincipal;
Thread.CurrentPrincipal = logicalPrincipal;
try
{
// anything called from here out will find the principal from your original thread
}
finally
{
// Revert to the original identity when work is complete
Thread.CurrentPrincipal = originalWorkerThreadPrincipal;
}
});
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)