重现问题
我们现在编写一个示例来重现一个异步刷信的问题。
首先,我们建立一个名为“ScriptHandler.ashx”的Generic Handler,它的作用是模拟一个脚本文件。可以看出,加载这么一个脚本文件是一个很耗时的操作。
ScriptHandler.ashx <%@ WebHandler Language="" Class="ScriptHandler" %> using System; using System.Web; public class ScriptHandler : IHttpHandler { public void ProcessRequest (HttpContext context) { context.Response.ContentType = "text/javascript"; System.Threading.Thread.Sleep(3000); context.Response.Write("Sys.Application.notifyScriptLoaded();"); } // } |
然后我们创建一个简单的页面,放置一个UpdatePanel和两个按钮。 Page
<asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <%= DateTime.Now %><br /> <asp:Button ID="Button1" runat="server" Text="Load Script File" OnClick="Button1_Click" /> <asp:Button ID="Button2" runat="server" Text="Partial Rendering" OnClick="Button2_Click" /> </ContentTemplate> </asp:UpdatePanel> |
下面的代码是响应按钮Click事件的实现。当我们点击“Load Script File”按钮时,ScriptHandler.ashx会被作为脚本文件添加到页面上。而“Partial Rendering”则会发起一个需要等待很长时间的异步刷新。
Event Handler protected void Button1_Click(object sender, EventArgs e) { ScriptManager.RegisterClientScriptInclude(this.Page, this.GetType(), "key", "ScriptHandler.ashx?m=" + new Random(DateTime.Now.Millisecond).Next()); } protected void Button2_Click(object sender, EventArgs e) { Thread.Sleep(5000); } |
您可以点击这里这个重现问题的示例并将它部署在您的机器上,您也可以点击这里察看这个页面。请一步一步跟着我来浏览这个页面,我会示范一下这个问题。
打开页面,我们可以看到时间和两个按钮。
点击“Load Script File” 按钮,并等待时间更新。
在时间更新后,点击“Partial Rendering” 按钮。
一般来说,最后一步之后大约5秒多钟,时间将会被跟新。但是现在您会发现,直到您重新点击某个按钮之后时间才会更新。事实上最后一步的任何操作,例如脚本加载,Hidden Field的注册都失败了,客户端生命周期的事件也不会触发。
原因何在?
在我分析客户端异步刷新的机制之前,我想简单的解释一些Script语言和DOM操作的基本特性。使用Script来操作页面中的DOM是AJAX技术的基础。有人说,JavaScript编程是没有多线程的,因此我们能够认为它始终线程