C#:在 ASP.NET 中向 Parallel.ForEach() 添加上下文 [英] C#: Adding context to Parallel.ForEach() in ASP.NET

查看:16
本文介绍了C#:在 ASP.NET 中向 Parallel.ForEach() 添加上下文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有静态 get 属性的静态类,在这个属性中,我这样做:

//属性体{//HttpContext.Current 不为空...Parallel.ForEach(文件,文件 =>{//HttpContext.Current 为空var promo = new Promotion();...});...//HttpContext.Current 不为空}

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

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

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

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

 var context = HttpContext.Current;Parallel.ForEach(文件,文件 =>{var promo = new Promotion(context);});

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

对此有哪些可能的解决方法?我没有意识到 HttpContext.CurrentParallel.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆