为什么.NET中递归绑定gridview会引发堆栈溢出问题?
堆栈溢出的根本原因是触发了数据绑定的无限递归循环,具体调用链如下:
- 页面首次加载(IsPostBack为false),GridView完成第一次数据绑定,触发
DataBound事件 - 执行
DBG_DataBound方法,命中!IsPostBack判断分支,调用SetPage方法 SetPage方法修改DBG.PageIndex属性,对于已经绑定了数据源的GridView控件,修改分页索引会自动触发控件重新执行数据绑定- 重新绑定完成后再次触发
DataBound事件,注意同一个请求生命周期内IsPostBack的值不会发生变化,所以仍然会命中!IsPostBack分支,再次调用SetPage - 上述流程无限循环,直到线程栈空间耗尽,抛出堆栈溢出错误。
附带的潜在问题
你在OnLoad方法中每次页面生命周期执行时,都会给LinqDS和DBG的事件追加新的匿名委托:
LinqDS.Selecting += delegate { ... }; LinqDS.Selected += delegate { ... }; DBG.DataBinding += delegate { ... }; DBG.DataBound += delegate { ... };
这些匿名委托不会被自动注销,同一次请求内如果触发多次绑定,这些委托会重复执行,多次请求后也会累积内存占用问题,建议将事件绑定逻辑移到if(!IsPostBack)分支内,或者在Page_Init阶段只绑定一次。
修复方案
修改DBG_DataBound的逻辑,只有当当前页索引和要设置的页索引不一致的时候才执行修改,避免重复触发绑定:
protected void DBG_DataBound(object sender, EventArgs e) { PageControls.Visible = DBG.PageCount > 1; if (!IsPostBack) { var key = GridKey; var targetPage = Session[key] != null ? (int)Session[key] : 0; // 仅当目标页和当前页不一致时才修改 if (DBG.PageIndex != targetPage) { SetPage(targetPage); } } }
内容的提问来源于stack exchange,提问作者Shibashish Mohanty
相关产品推荐
相关产品推荐

