Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#:向ASP.NET中的Parallel.ForEach()添加上下文_C#_Asp.net_Multithreading_Parallel Processing - Fatal编程技术网

C#:向ASP.NET中的Parallel.ForEach()添加上下文

C#:向ASP.NET中的Parallel.ForEach()添加上下文,c#,asp.net,multithreading,parallel-processing,C#,Asp.net,Multithreading,Parallel Processing,我有一个带有静态get属性的静态类,在该属性中,我执行以下操作: // property body { // HttpContext.Current is NOT null ... Parallel.ForEach(files, file => { // HttpContext.Current is null var promo = new Promotion(); ... }); ...

我有一个带有静态get属性的静态类,在该属性中,我执行以下操作:

// property body
{
    // HttpContext.Current is NOT null
    ...

    Parallel.ForEach(files, file =>
    {
        // HttpContext.Current is null
        var promo = new Promotion();
        ...
    });
    ...

    // HttpContext.Current is NOT null
}
在视图使用此属性之前,此静态类不会进行类型初始化

问题在于,
Promotion
的静态构造函数使用
HttpContext.Current
,该构造函数在
Parallel.ForEach()
中第一次创建
new Promotion()
时初始化。当
promo
在此
Parallel.ForEach()
范围内实例化时,
HttpContext.Current
null
,因此
new Promotion()
会导致异常

HttpContext.Current
在静态get属性中不为null,因为在视图使用它之前不会调用它(因此存在
HttpContext.Current

如果
Promotion
在其实例中而不是在其静态成员中使用
HttpContext.Current
,我可能只需将
HttpContext.Current
传递到
new Promotion()
构造函数中:

 var context = HttpContext.Current;
 Parallel.ForEach(files, file =>
 {
     var promo = new Promotion(context);
 });
但是由于
static
Promotion的成员需要HttpContext.Current,我不能。我可能会重新设计
升级
类,以将需要它的静态成员更改为实例成员,但它们是静态的,这是有原因的——如果每次实例化
新升级
时都必须在每个实例上定义所有静态成员,则会造成很大的性能损失


这方面可能的解决办法是什么?我没有意识到
HttpContext.Current
Parallel.ForEach()

HttpContext.Current的范围内将为null,因为它在“非web线程”中运行。如果您使用
newthread(…)
来分叉一些代码,它将完全相同。TPL在某种程度上隐藏了这一点,但您仍然需要认识到,
并行.ForEach
中的每个迭代都可能在不同的线程中运行,并相应地处理它

特别是,如果您想在web请求之外使用某些类或方法(Parallel.ForEach就是这样一种用法),您就不能使用HttpContext.Current。一种解决方法是在构造函数中显式传递HttpContext(或HttpContextBase,以提高可测试性)(或作为方法参数)


简而言之:您需要打破使用HttpContext.Current的静态模式。

正如Mauricio指出的,
HttpContext.Current取决于当前执行的线程。静态构造函数依赖于诸如
HttpContext.Current
这样的固有瞬态值,这让我感到很不寻常,但这可能不是您的想法

如果您可以更改<代码>促销>代码>类,那将是我考虑的第一个选项。 如果不是,您需要在

HttpContext.Current
仍然有效的位置强制执行
Promotion
的类型初始化。要了解什么强制初始化类型,请阅读


一个选项可以是创建一个虚拟的
Promotion
对象(在整个程序中只创建一次就足够了)。如果这不是一个选项,您可以尝试通过使用反射读取属性。我不知道这是否会强制类型初始化,但我想是的

只需将Parallel.ForEach调用外部的任何上下文向下传递到依赖于所述上下文的内部调用的任何函数中即可

var context = HttpContext.Current;
Parallel.ForEach(items, item =>
    {
        DoSomething(item, context);
    }
);



private static void DoSomething(item, context = null) {
    if (context == null) context = HttpContext.Current;

    ...
}

我喜欢回退到null,这样我就不必一直担心传递上下文。我只确保在从另一个线程调用时,我的函数需要上下文,然后我就把它放在那里。

它不起作用,因为在foreach中创建了一个新线程,所以上下文为空。即使创建一个方法DoSomething来设置curren上下文,上下文仍然为空。

当第一次接触类的代码时,升级的静态成员将只初始化一次。。。。它们如何依赖于
HttpContext.Current
?促销的源代码是否在您的控制之下?