0

メモリが不足した後に停止するWPFアプリがあります...
これは基本的に、LinqToSqlまたはGeneratedクラスICTemplates.Segmentのインスタンスであるノードを表示するTreeViewです。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の子を持つノードを展開すると、子が読み込まれるまでにしばらく時間がかかります(タスクマネージャーはMemの使用状況を1000000Kと表示します!)。次のノードを約50人の子で拡張すると、BOOM!OutOfMemoryException

VSプロファイラーを実行してさらに深く掘り下げました。結果は次のとおりです。

概要ページ オブジェクトの有効期間の 割り当て

上位3つは、Action、DeferredSourceFactory.DeferredSource、およびEntitySet(すべての.Net / LINQクラス)です。唯一のユーザークラスはSegment[]であり、Segmentは#9と#10で提供されます。

私は追求するためのリードを考えることができません..理由は何でしょうか?

4

4 に答える 4

1

多分その DataContext を囲む使用?

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

また、SQL プロファイラーを使用してみましたか? 問題に光を当てるかもしれません。

于 2009-01-09T07:40:42.363 に答える
0

要素ごとに 1 つではなく、グローバルな DataContext を使用してみましたか?

独自のクエリと結果を持つすべての DataContext をそれぞれ作成すると、メモリが膨張する可能性があります。

于 2009-01-08T21:37:19.557 に答える
0

問題は、シロッコが言及した複数の S1DataContext オブジェクトの作成にあるようです。Dispose を強制してコレクションの対象にするために using ステートメントを試しました。ただし、意味をなさない ObjectDisposedException が発生しました。

  1. コントロールは、DockPanel KeeperOfAllControls のデータ コンテキストを設定する行から始まります。
  2. [外部コード] (コールスタックに表示)
  3. Segment.Children.get (dc の using ブロックがあります)
  4. ステップ 1 の行に戻ります... ObjectDisposedExceptionLinq クエリは、S1DataContext のローカル インスタンスから取得された tblSegments を使用します

とにかく、複数の DataContext が作成および破棄されないようにする何かがあると思います。だから私は Singleton DataContext を試しました
そしてそれはうまくいきます!

  • TreeView コントロールの応答性が大幅に向上し、試したすべてのノードが最大 3 ~ 4 秒でロードされます。
  • すべてのフェッチ/検索の前に GC.Collect (検証用) を入れたところ、メモリ使用量は 200,000 ~ 300,000K にとどまりました。

OR で生成された System.Data.Linq.DataContext は、明示的に破棄されない限り (メモリを消費しない限り) 消えないようです。私の場合、それを破棄しようとしましたが、うまくいきませんでした..両方の関数に独自の使用ブロックがありましたが(DataContextの共有インスタンスはありません)。シングルトンは嫌いですが、開発者向けの小さな内部ツールを作成しているので、今のところ気にしません..オンラインで見たLinqToSqlサンプルはどれも.. Dispose呼び出しが義務付けられていませんでした.

それで問題は解決したと思います。このバグを浅くするために、より多くの目玉として行動したすべての人々に感謝します.

于 2009-01-09T10:51:48.657 に答える
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;
  }
}
于 2009-01-09T07:34:42.750 に答える