tl;dr:如果您在使用 Webforms 时遇到此问题,并且不需要对该特定页面中的会话状态进行写访问,请添加EnableSessionState="ReadOnly"
给你的@Page
指令有帮助。
显然,存在Session_Start
单独强制 ASP.NET 按顺序执行源自同一会话的所有请求。但是,如果您不需要会话的写访问权限,则可以逐页修复此问题(见下文)。
I've created my own test setting with Webforms, which uses an aspx page to deliver images.1
这是测试页面(纯 HTML,项目的起始页面):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title></title></head>
<body>
<div>
<img src="GetImage.aspx?text=A" />
<img src="GetImage.aspx?text=B" />
<img src="GetImage.aspx?text=C" />
<img src="GetImage.aspx?text=D" />
<img src="GetImage.aspx?text=E" />
<img src="GetImage.aspx?text=F" />
<img src="GetImage.aspx?text=G" />
<img src="GetImage.aspx?text=H" />
<img src="GetImage.aspx?text=I" />
<img src="GetImage.aspx?text=J" />
<img src="GetImage.aspx?text=K" />
<img src="GetImage.aspx?text=L" />
</div>
</body>
</html>
这是 aspx 页面 (GetImage.aspx):
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="GetImage.aspx.cs" Inherits="CsWebApplication1.GetImage" %>
以及代码隐藏的相关部分(GetImage.aspx.cs,using
and namespace
跳过):
public partial class GetImage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Debug.WriteLine("Start: " + DateTime.Now.Millisecond);
Response.Clear();
Response.ContentType = "image/jpeg";
var image = GetDummyImage(Request.QueryString["text"]);
Response.OutputStream.Write(image, 0, image.Length);
Debug.WriteLine("End: " + DateTime.Now.Millisecond);
}
// Empty 50x50 JPG with text written in the center
private byte[] GetDummyImage(string text)
{
using (var bmp = new Bitmap(50, 50))
using (var gr = Graphics.FromImage(bmp))
{
gr.Clear(Color.White);
gr.DrawString(text,
new Font(FontFamily.GenericSansSerif, 10, FontStyle.Regular, GraphicsUnit.Point),
Brushes.Black, new RectangleF(0, 0, 50, 50),
new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
using (var stream = new MemoryStream())
{
bmp.Save(stream, ImageFormat.Jpeg);
return stream.ToArray();
}
}
}
}
试运行
Run 1,未修改:页面加载速度快,输出窗口显示随机组合Start
and End
s,这意味着请求得到并行处理。
Run 2,添加空Session_Start
to global.asax
(需要在浏览器中按一次F5,不知道这是为什么):Start
and End
交替,显示请求按顺序处理。多次刷新浏览器表明,即使未附加调试器,也会存在性能问题。
Run 3,与运行 2 类似,但添加EnableSessionState="ReadOnly"
to the @Page
的指令GetImage.aspx
:调试输出显示多个Start
s 在第一个之前End
。我们又并行了,而且表现不错。
1 Yes, I know that this should be done with an ashx handler instead. It's just an example.