C#:在 ASP.NET 中向 Parallel.ForEach() 添加上下文 [英] C#: Adding context to Parallel.ForEach() in ASP.NET
问题描述
我有一个带有静态 get 属性的静态类,在这个属性中,我这样做:
//属性体{//HttpContext.Current 不为空...Parallel.ForEach(文件,文件 =>{//HttpContext.Current 为空var promo = new Promotion();...});...//HttpContext.Current 不为空}
在视图使用此属性之前,此静态类不会进行类型初始化.
问题在于 Promotion
的静态构造函数,它在 Parallel.ForEach() 中第一次创建
,使用new Promotion()
时被初始化HttpContext.Current
.当 promo
在此 Parallel.ForEach()
范围内实例化时,HttpContext.Current
为 null
,并且new Promotion()
因此导致异常.
HttpContext.Current
在静态 get 属性中不为空,因为它在视图使用它之前不会被调用(因此有一个 HttpContext.Current
).>
如果 Promotion
在其实例中使用 HttpContext.Current
而不是其静态成员,我可能只需将 HttpContext.Current
传递到 HttpContext.Current
code>new Promotion() 构造函数:
var context = HttpContext.Current;Parallel.ForEach(文件,文件 =>{var promo = new Promotion(context);});
但是由于Promotion的static
成员需要HttpContext.Current,我不能.我可能会重新设计 Promotion
类来更改需要它作为实例成员的静态成员,但它们是静态的是有原因的——如果所有成员都是静态的,则会有很大的性能损失每次实例化 new Promotion
时,都必须在每个实例上定义.
对此有哪些可能的解决方法?我没有意识到 HttpContext.Current
在 Parallel.ForEach()
的范围内会是 null.
HttpContext.Current 为 null,因为它在非 Web 线程"中运行.如果你使用 new Thread(...)
分叉一些代码,它会完全一样.TPL 在某种程度上隐藏了这一点,但您仍然需要意识到 Parallel.ForEach
中的每次迭代都可能在不同的线程中运行,并相应地对其进行处理.
特别是,如果您想在 Web 请求之外使用某个类或方法(而 Parallel.ForEach 就是这样一种用法),您就不能使用 HttpContext.Current.解决方法是在构造函数中(或作为方法参数)显式传递 HttpContext(或 HttpContextBase 以提高可测试性)
简而言之:您需要摆脱静态使用 HttpContext.Current.
I have a static class with a static get property, and in this property, I do this:
// property body
{
// HttpContext.Current is NOT null
...
Parallel.ForEach(files, file =>
{
// HttpContext.Current is null
var promo = new Promotion();
...
});
...
// HttpContext.Current is NOT null
}
This static class doesn't undergone type initialization until a view uses this property.
The problem is that Promotion
's static constructor, which is initialized the first time a new Promotion()
is created within the Parallel.ForEach()
, uses HttpContext.Current
. When promo
is instantiated within the scope of this Parallel.ForEach()
, HttpContext.Current
is null
, and new Promotion()
therefore causes an exception.
HttpContext.Current
is not null within the static get property because it's not called until the view uses it (and there is therefore a HttpContext.Current
).
If Promotion
used HttpContext.Current
in its instances instead of its static members, I could probably just pass HttpContext.Current
into the new Promotion()
constructor:
var context = HttpContext.Current;
Parallel.ForEach(files, file =>
{
var promo = new Promotion(context);
});
But since static
members of Promotion need HttpContext.Current, I can't. I could probably redesign the Promotion
class to change the static members that need it to be instance members, but they are static for a reason--there would be a large performance penalty if all the members that were static had to be defined instead on each instance each time a new Promotion
was instantiated.
What are the possible workarounds for this? I didn't realize HttpContext.Current
would be null within the scope of Parallel.ForEach()
.
HttpContext.Current is null because it's running in "non-web threads". If you forked some code using new Thread(...)
it would be exactly the same. The TPL somewhat hides this, but you still need to realize that each iteration in your Parallel.ForEach
can potentially run in a different thread, and treat it accordingly.
In particular, if you want to use some class or method out of the web request (and Parallel.ForEach is such an usage) you just can't use HttpContext.Current. A workaround is to explicitly pass the HttpContext (or HttpContextBase for improved testability) in the constructor (or as a method parameter)
In a nutshell: you need to break out of using HttpContext.Current statically.
这篇关于C#:在 ASP.NET 中向 Parallel.ForEach() 添加上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!