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

Sni*_*ave 12 c# asp.net parallel-processing multithreading

我有一个带静态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
}
Run Code Online (Sandbox Code Playgroud)

在视图使用此属性之前,此静态类不会进行类型初始化.

问题是,Promotion的静态构造函数,初始化第一次new Promotion()被内创建Parallel.ForEach(),使用HttpContext.Current.何时promo在此范围内实例化Parallel.ForEach(),HttpContext.Currentnull,new Promotion()因此导致异常.

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

如果Promotion使用HttpContext.Current在它的实例,而不是它的静态成员,我很可能只是传递HttpContext.Currentnew Promotion()构造函数:

 var context = HttpContext.Current;
 Parallel.ForEach(files, file =>
 {
     var promo = new Promotion(context);
 });
Run Code Online (Sandbox Code Playgroud)

但由于staticPromotion的成员需要HttpContext.Current,我不能.我可能会重新设计Promotion类来将需要它的静态成员更改为实例成员,但它们是静态的 - 如果所有静态成员都必须在每个实例上定义,那么会有很大的性能损失每次a new Promotion实例化.

有什么可行的解决方法?我没有意识到HttpContext.Current在范围内会无效Parallel.ForEach().

Mau*_*fer 11

HttpContext.Current为null,因为它在"非Web线程"中运行.如果你使用new Thread(...)它分叉一些代码就完全一样了.TPL在某种程度上隐藏了这一点,但您仍然需要意识到您的每个迭代Parallel.ForEach都可能在不同的线程中运行,并相应地对其进行处理.

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

简而言之:你需要静态地使用HttpContext.Current.