We are running a very large web application in asp.net MVC .NET 4.0. Recently we had an audit done and the performance team says that there were a lot of null reference exceptions.
我们正在asp.net MVC。4.0中运行一个非常大的web应用程序。最近我们进行了一次审计,性能团队说有很多空引用异常。
So I started investigating it from the dumps and event viewer. My understanding was as follows:
所以我开始从转储和事件查看器中研究它。我的理解如下:
We are using Asyn Tasks in our controllers. We rely on HttpContext.Current.Items hashtable to store a lot of Application level values.
我们在控制器中使用Asyn任务。我们依靠HttpContext.Current。Items hashtable用于存储许多应用程序级别的值。
Task<Articles>.Factory.StartNew(() =>
{
System.Web.HttpContext.Current = ControllerContext.HttpContext.ApplicationInstance.Context;
var service = new ArticlesService(page);
return service.GetArticles();
}).ContinueWith(t => SetResult(t, "articles"));
So we are copying the context object onto the new thread that is spawned from Task factory. This context.Items is used again in the thread wherever necessary. Say for ex:
因此,我们将上下文对象复制到从Task factory生成的新线程上。这个上下文。只要有必要,在线程中再次使用项。对前女友说:
public class SomeClass
{
internal static int StreamID
{
get
{
if (HttpContext.Current != null)
{
return (int)HttpContext.Current.Items["StreamID"];
}
else
{
return DEFAULT_STREAM_ID;
}
}
}
This runs fine as long as number of parallel requests are optimal. My questions are as follows:
只要并行请求的数量是最优的,这就可以很好地运行。我的问题如下:
1. When the load is more and there are too many parallel requests, I notice that HttpContext.Current.Items is empty. I am not able to figure out a reason for this and this causes all the null reference exceptions.
1。当负载更大且有太多并行请求时,我注意到HttpContext.Current。项目是空的。我无法找出原因,这会导致所有的空引用异常。
2. How do we make sure it is not null ? Any workaround if present ?
2。如何确保它不是null ?有什么办法吗?
NOTE: I read through in * and people have questions like HttpContext.Current is null - but in my case it is not null and its empty. I was reading one more article where the author says that sometimes request object is terminated and it may cause problems since dispose is already called on objects. I am doing a copy of Context object - its just a shallow copy and not a deep copy.
注意:我在*中浏览了一遍,人们有像HttpContext这样的问题。Current是空的——但是在我的例子中,它不是空的。我又读了一篇文章,作者说有时候请求对象会被终止,这可能会导致问题,因为对对象已经调用了dispose。我正在做一个Context对象的拷贝——它只是一个浅拷贝而不是一个深拷贝。
2 个解决方案
#1
2
Your problem is that a instance members of the HttpContext are not thread safe:
您的问题是HttpContext的实例成员不是线程安全的:
Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.
这种类型的任何公共静态(在Visual Basic*享)成员都是线程安全的。任何实例成员都不能保证是线程安全的。
When accessing it the way you are doing (multiple threads) you need to do your own synchronization.
当您使用(多线程)访问它时,您需要进行自己的同步。
static object locker = new object();
get
{
lock (locker)
{
if (HttpContext.Current != null)
{
return (int)HttpContext.Current.Items["StreamID"];
}
else
{
return DEFAULT_STREAM_ID;
}
}
}
MSDN:system.web.httpcontext
#2
0
Maybe I'm misreading this, but I'm getting the impression that you're only trying to prevent the null reference error.
也许我读错了,但是我得到的印象是你只是想防止零引用错误。
public class SomeClass
{
internal static int StreamID
{
get
{
int returnValue;
if (HttpContext.Current != null)
{
if(HttpContext.Current.Items["StreamID"] != null)
{
returnValue = (int)HttpContext.Current.Items["StreamID"];
}
else
{
returnValue = DEFAULT_STREAM_ID;
}
}
else
{
returnValue = DEFAULT_STREAM_ID;
}
return returnValue;
}
}
}
#1
2
Your problem is that a instance members of the HttpContext are not thread safe:
您的问题是HttpContext的实例成员不是线程安全的:
Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.
这种类型的任何公共静态(在Visual Basic*享)成员都是线程安全的。任何实例成员都不能保证是线程安全的。
When accessing it the way you are doing (multiple threads) you need to do your own synchronization.
当您使用(多线程)访问它时,您需要进行自己的同步。
static object locker = new object();
get
{
lock (locker)
{
if (HttpContext.Current != null)
{
return (int)HttpContext.Current.Items["StreamID"];
}
else
{
return DEFAULT_STREAM_ID;
}
}
}
MSDN:system.web.httpcontext
#2
0
Maybe I'm misreading this, but I'm getting the impression that you're only trying to prevent the null reference error.
也许我读错了,但是我得到的印象是你只是想防止零引用错误。
public class SomeClass
{
internal static int StreamID
{
get
{
int returnValue;
if (HttpContext.Current != null)
{
if(HttpContext.Current.Items["StreamID"] != null)
{
returnValue = (int)HttpContext.Current.Items["StreamID"];
}
else
{
returnValue = DEFAULT_STREAM_ID;
}
}
else
{
returnValue = DEFAULT_STREAM_ID;
}
return returnValue;
}
}
}