tl;dr:如果您在使用 Web 表单时遇到此问题,并且不需要对该特定页面中会话状态的写入权限,则将 EnableSessionState="ReadOnly" 添加到您的 @Page 指令会有所帮助。
显然,仅Session_Start 的存在就迫使 ASP.NET 依次执行源自同一 Session 的所有请求。但是,如果您不需要对会话的写入权限,则可以逐页修复此问题(见下文)。
我使用 Webforms 创建了自己的测试设置,它使用 aspx 页面来传递图像。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 和 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 和Ends 的随机混合,这意味着请求得到并行处理。
运行2,将空Session_Start添加到global.asax(需要在浏览器中按F5一次,不知道这是为什么):Start和@987654334 @alternate,表明请求是按顺序处理的。多次刷新浏览器表明即使没有附加调试器也会出现性能问题。
运行 3,与运行 2 类似,但将 EnableSessionState="ReadOnly" 添加到 GetImage.aspx 的 @Page 指令中:调试输出在第一个 @987654339 之前显示多个 Starts @。我们又并行了,性能不错。
1 是的,我知道这应该使用 ashx 处理程序来代替。这只是一个例子。