2009-01-08 60 views
0

我有一個WPF應用程序正在研磨到內存不足時暫停...
它基本上是一個TreeView顯示節點,它是Linq To Sql或生成的類ICTemplates.Segment的實例。在OR設計器中,通過關聯間接鏈接了大約20個表。爲什麼我的WPF Treeview綁定到LinqToSql類是內存豬?

<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的顯式屬性給segment類,它使用父子記錄查找另一個表。

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控件。

我非常確定,孩子們正在按需加載(當我展開父母)按響應時間。當我使用大約孩子展開一個節點時,加載子項需要一段時間(任務管理器顯示內存使用量爲1000000K!)。如果我用大約50個孩子展開下一個節點,BOOM! OutOfMemoryException異常

我跑VS探查深入挖掘和這裏的結果

Summary Page Object Lifetimes Allocation

排名前3名的行動,DeferredSourceFactory.DeferredSource和EntitySet的(所有的.NET/LINQ類) 。唯一的用戶類是Segment []和Segment分別以#9和#10進入。

我想不出一個主角去追求..可能是什麼原因?

回答

0

這個問題似乎是創建多個S1DataContext對象Sirocco提到。 我嘗試使用聲明來強制Dispose並使其符合收集條件。然而,它導致了我無法理解的ObjectDisposedException。

  1. 該控件從設置DockPanel KeeperOfAllControls的數據上下文的行開始。
  2. [外部代碼]
  3. Segment.Children.get(在調用棧示出)(已經使用一個塊與DC)
  4. 回到線路在步驟1 ... ObjectDisposedException LINQ查詢使用tblSegments這是從本地實例S1DataContext檢索

總之,所以我認爲有一些東西,防止多個DataContexts被創建和處置。所以我試過了Singleton DataContext
它的工作原理!

  • TreeView控件響應性更強,我試過的每個節點都在3-4秒內加載最大。
  • 我在每次抓取/搜索之前放入GC.Collect(用於驗證),現在內存使用量保持在200,000-300,000K之間。

OR生成的System.Data.Linq.DataContext似乎不會消失,除非它明確地放置(進食記憶)。試圖放棄它在我的情況下,並沒有氾濫......即使這兩個函數都有自己的使用塊(沒有DataContext的共享實例)。儘管我不喜歡單身人士,但我正在爲開發人員製作一個小型內部工具,因此現在不介意它們..我在線看到的LinqToSql示例中沒有一個具有強制Dispose調用。

所以我想這個問題已經修復。感謝所有那些充當更多眼球的人,讓這個bug變淺。

0

您是否嘗試過使用全局DataContext而不是每個元素?

創建所有的DataContext的每個與自己的查詢和結果可能是你的內存膨脹的原因。

+0

更新後的問題...我爲每個查詢設置一次DataContext ...不是針對每個元素/節點。 – Gishu 2009-01-09 06:54:48

0

我不知道確切的解決方案,但join中的新語句可能會導致此問題。因爲每個關係都可以創建一個新對象(但正如我所提到的,我不知道它是否正確)。

你可以試試這個;

public IEnumerable<Segment> Children 
{ 
    get 
    { 
    System1ConfigDataContext dc = new System1ConfigDataContext(); 
    return from link in this.ChildLinks 
     join segment in dc.Segments on link.ChildSite == segment.site && link.ChildSID == segment.id 
     select segment; 
    } 
} 
+0

上面的代碼片段不會編譯 - 錯誤CS0744:預期的上下文關鍵字'等於'。我已經在LINQ中使用連接語法進行了小規模戰鬥。新要求 - 請參閱http://stackoverflow.com/questions/373865/whats-the-best-way-to-model-parent-child-relationships-stored-in-a-join-table-in – Gishu 2009-01-09 09:23:54

+0

嗯,我明白了。順便說一句,謝謝。 – 2009-01-09 14:08:31

1

也許是使用DataContext?

using(System1ConfigDataContext dc = new System1ConfigDataContext()){ 
    .... ? 
} 

此外,您是否嘗試過使用sql profiler?可能會對這件事情有所瞭解。

+0

感謝Sirocco。你讓我走在正確的道路上......謝謝!看到我的帖子下面的細節.. – Gishu 2009-01-09 10:35:10