为什么我的 WPF Treeview 绑定到 LinqToSql 类会占用大量内存?
我有一个 WPF 应用程序,它在内存不足后停止运行...
它基本上是一个显示节点的 TreeView,这些节点是 Linq To Sql 或生成的类 ICTemplates.Segment 的实例。 在 OR 设计器中,大约有 20 个表通过关联间接链接到此类。
<TreeView Grid.Column="0" x:Name="tvwSegments"
ItemsSource="{Binding}"
SelectedItemChanged="OnNewSegmentSelected"/>
<HierarchicalDataTemplate DataType="{x:Type local:Segment}" ItemsSource="{Binding Path=Children}">
...
// code behind, set the data context based on user-input (Site, Id)
KeeperOfControls.DataContext = from segment in tblSegments
where segment.site == iTemplateSite && segment.id == iTemplateSid
select segment;
我在段类中添加了一个名为 Children 的显式属性,该属性查找另一个包含父子记录的表。
public IEnumerable<Segment> Children
{
get
{
System1ConfigDataContext dc = new System1ConfigDataContext();
return from link in this.ChildLinks
join segment in dc.Segments on new { Site = link.ChildSite, ID = link.ChildSID } equals new { Site = segment.site, ID = segment.id }
select segment;
}
}
其余部分是数据绑定与数据模板相结合,将每个段显示为一组 UI 控件。
我非常确定子级是根据响应时间按需加载的(当我展开父级时)。 当我展开一个包含大约 70 个子节点的节点时,需要一段时间才能加载子节点(任务管理器显示内存使用情况为 1000000K!)。 如果我用大约 50 个子节点扩展下一个节点,轰隆隆! OutOfMemoryException
我运行 VS Profiler 进行更深入的研究,结果如下
前 3 名是 Action、DeferredSourceFactory.DeferredSource 和 EntitySet(全部.Net/LINQ 类)。 唯一的用户类是 Segment[] 和 Segment,排在第 9 和第 10 名。
我想不出要追寻的线索。原因可能是什么?
I have a WPF App which is grinding to a halt after running out of memory...
It is basically a TreeView displaying nodes, which are instances of Linq To Sql OR Generated class ICTemplates.Segment. There around 20 tables indirectly linked via associations to this class in the OR designer.
<TreeView Grid.Column="0" x:Name="tvwSegments"
ItemsSource="{Binding}"
SelectedItemChanged="OnNewSegmentSelected"/>
<HierarchicalDataTemplate DataType="{x:Type local:Segment}" ItemsSource="{Binding Path=Children}">
...
// code behind, set the data context based on user-input (Site, Id)
KeeperOfControls.DataContext = from segment in tblSegments
where segment.site == iTemplateSite && segment.id == iTemplateSid
select segment;
I've added an explicit property called Children to the segment class which looks up another table with parent-child records.
public IEnumerable<Segment> Children
{
get
{
System1ConfigDataContext dc = new System1ConfigDataContext();
return from link in this.ChildLinks
join segment in dc.Segments on new { Site = link.ChildSite, ID = link.ChildSID } equals new { Site = segment.site, ID = segment.id }
select segment;
}
}
The rest of it is data binding coupled with data templates to display each Segment as a set of UI Controls.
I'm pretty certain that the children are being loaded on-demand (when I expand the parent) going by the response time. When I expand a node with around 70 children, it takes a while before the children are loaded (Task manager shows Mem Usage as 1000000K!). If I expand the next node with around 50 children, BOOM! OutOfMemoryException
I ran the VS Profiler to dig deeper and here are the results
Summary Page
Object Lifetimes
Allocation
The top 3 are Action, DeferredSourceFactory.DeferredSource and EntitySet (all .Net/LINQ classes). The only user-classes are Segment[] and Segment come in at #9 an #10.
I can't think of a lead to pursue.. What could be the reason ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
也许是围绕 DataContext 的使用?
另外,您是否尝试过使用sql profiler? 可能会对此事有所启发。
maybe a using surrounding that DataContext ?
also, have you tried using an sql profiler? might shed some light on the matter.
您是否尝试过使用全局 DataContext 而不是每个元素使用一个全局 DataContext?
使用自己的查询和结果创建所有 DataContext 可能会导致内存膨胀。
Have you tried using a global DataContext instead of one for each element?
Creating all of the DataContext's each with there own query and results could be the cause of your memory bloat.
我不知道确切的解决方案,但 join 中的新语句可能会导致此问题。 因为对于每个关系都可以创建一个新对象(但正如我提到的,我不知道它是否正确)。
你能试试这个吗?
I don't know the exact solution but the new statement in join may cause this. Because for each relation a new object could be created(But as I mentioned, I don't know if it is correct).
Could you try this;
问题似乎是创建多个 S1DataContext 对象,如 Sirocco 所提到的。
我尝试使用 using 语句来强制 Dispose 并使其符合收集条件。 然而,它导致了一个我无法理解的 ObjectDisposeException 。
无论如何,所以我假设有一些东西阻止创建多个 DataContext处置。 所以我尝试了单例DataContext。
它有效!
OR 生成的 System.Data.Linq.DataContext 似乎不会消失,除非显式处置它(占用内存)。 尝试在我的情况下处理它,但没有成功..即使两个函数都有自己的 using 块(没有 DataContext 的共享实例)。 虽然我不喜欢 Singleton,但我正在为开发人员制作一个小型内部工具,因此现在不介意它。我在网上看到的 LinqToSql 示例都没有强制执行 Dispose 调用。
所以我想问题已经解决了。 感谢所有充当更多眼球的人,让这个 bug 变得浅薄。
The issue seems to be the creation of multiple S1DataContext objects as Sirocco referred to.
I tried the using statement to force a Dispose and make it eligible for collection. However it resulted in an ObjectDisposedException that I can't make sense of.
Anyways so i assume that there is something that prevents multiple DataContexts from being created and disposed. So I tried a Singleton DataContext.
And it works!
The OR generated System.Data.Linq.DataContext doesn't seem to go away unless it is disposed explicitly (eating memory). Trying to Dispose it in my case, didn't pan out.. even though both functions had their own using blocks (no shared instance of DataContext). Though I dislike Singletons, I'm making a small internal tool for devs and hence don't mind it as of now.. None of the LinqToSql samples I saw online.. had Dispose calls mandated.
So I guess the problem has been fixed. Thanks to all the people that acted as more eyeballs to make this bug shallow.