ASP.NET Web Forms长耗时方法执行期间如何触发前端显示加载通知弹窗
问题排查与解决方案
核心问题根因
你的实现完全不符合ASP.NET WebForm的请求-响应生命周期机制,核心错误有两个:
- 同步回传的机制限制:AutoPostBack本质是同步全页面回传,用户选中下拉项后,请求会先发到服务端,服务端必须跑完整个页面生命周期的所有逻辑(包括数据拉取操作),才会把最终生成的页面内容返回给客户端。你在服务端调用
rnloading.Show()只是给返回的响应添加了一段显示弹窗的脚本,这段脚本必须等响应完全回到浏览器才会执行,自然会等到数据加载完才显示弹窗。 - BackgroundWorker用法完全错误:
- WebForm的页面对象仅在当前请求生命周期内有效,请求处理完成就会被销毁,你开后台线程拉取数据,等线程跑完的时候页面对象已经释放了,数据绑定操作根本不会生效
- 你在后台线程直接操作
txtInventoryItemID等页面控件,属于跨线程访问控件,会引发不可预期的阻塞或异常 - 如果你额外配置了让主线程等待后台线程跑完再返回响应,那和直接在主线程拉数据没有任何区别,还是会卡住整个请求。
正确实现方案
推荐你用WebForm原生的UpdatePanel + UpdateProgress方案,改动最小,不需要重构大量逻辑:
第一步:修改前端aspx代码
把需要异步更新的控件都放到UpdatePanel容器内,新增UpdateProgress控件专门用来显示加载提示:
<!-- 异步更新容器 --> <asp:UpdatePanel runat="server" ID="updMain"> <ContentTemplate> <!-- 原有下拉框、表格行、下拉选项控件都放在这个容器内 --> <asp:DropDownList runat="server" ID="ddlRequestType" AutoPostBack="true" OnSelectedIndexChanged="ddlRequestType_SelectedIndexChanged1" /> <tr runat="server" ID="trInventoryItemID"><!-- 原有内容 --></tr> <tr runat="server" ID="trItemDescription"><!-- 原有内容 --></tr> <asp:DropDownList runat="server" ID="txtInventoryItemID"></asp:DropDownList> </ContentTemplate> </asp:UpdatePanel> <!-- 加载提示控件,异步请求发起时自动显示,结束自动隐藏 --> <asp:UpdateProgress runat="server" ID="updProgress" AssociatedUpdatePanelID="updMain"> <ProgressTemplate> <div style="position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);padding:20px;background:#fff;border:1px solid #ccc;z-index:9999;"> Please wait loading </div> </ProgressTemplate> </asp:UpdateProgress>
第二步:修改服务端逻辑
删掉所有BackgroundWorker相关的代码,直接在选中事件里拉数据绑定即可:
protected void ddlRequestType_SelectedIndexChanged1(object sender, EventArgs e) { if (ddlRequestType.SelectedValue == "7") { trInventoryItemID.Visible = true; trItemDescription.Visible = true; // 直接拉取数据绑定,不需要开后台线程 var dataTable = new DataTable(); dataTable.Load(InventoryItem.GetInactiveInventory(ddlClients.SelectedItem.Text)); txtInventoryItemID.DataSource = dataTable; txtInventoryItemID.DataTextField = "PieceCode"; txtInventoryItemID.DataValueField = "Descrip"; txtInventoryItemID.DataBind(); } else { trInventoryItemID.Visible = false; trItemDescription.Visible = false; } }
这个方案的原理是UpdatePanel会把原本的同步回传改成异步AJAX请求,UpdateProgress会在请求发起的同时直接在前端显示加载提示,不需要服务端控制,请求处理完成后自动隐藏提示,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Ben Lokos
相关产品推荐
相关产品推荐

