にコンポーネントのラインナップ:子どもたち。に除去できます。明らかな無料オブジェ

StackOverflow https://stackoverflow.com/questions/2541684

質問

更新:またこの他に、より綺麗にされます。な再現ができます。を発見した場合はどのような違反(VSStudioコンポーネントの原因は、このようにしまいます。

私が作成したもUIElementsからコードを背景とした先のガベージコレクションを明確にすること。しかし、オブジェはフリーではありません-edの見です。見られfreeedでRemoveAt(0)がないから解放された後にプログラム。

どのように持ってもらうようにしてい物を解き放たれた時には、子どもたちからのキャンバス?

<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300"
    MouseDown="Window_MouseDown">
  <Grid>
    <Canvas x:Name="main" />
  </Grid>
</Window>

すべてのコードは:

public partial class MainWindow : Window
{
  public MainWindow()
  {
    InitializeComponent();
  }

private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
  GC.Collect(); // This should pick up the control removed at a previous MouseDown
  GC.WaitForPendingFinalizers(); // Doesn't help either

  if (main.Children.Count == 0)
    main.Children.Add(new MyControl() { Background = Brushes.Yellow, Width = 100, Height = 50 });
  else
    main.Children.RemoveAt(0);
 }
}

public class MyControl : UserControl
{
  ~MyControl()
  {
    Debug.WriteLine("Goodbye");
  }
}

正しい解決策はありません

他のヒント

変更

public class MyControl : UserControl

public class MyControl : ContentControl

とそれが(2回目以降のコントロールを削除します。)さよならを言うだろう、私はまた、メモリが

を使用して漏れない検証

Debug.WriteLine("mem: " + GC.GetTotalMemory(true).ToString());

また、このを参照:

  

あなたはクリアgrid.ChildrenによってTestControlを削除しますが、それはすぐにガベージコレクションの対象ではありません。 (これらがアンロードイベントおよびレンダリングエンジンの一部のクリーンアップコードを上げるなどが)その上で、いくつかの非同期操作が保留されている、そしてそれは完全にそれらの操作までGC'dをすることはできません。

     

私は、あなたが完全にこれらの操作(ContextIdleの優先順位でディスパッチャの操作をスケジュールすることによって言う)まで待っていれば、TestControlはTextBlockの上の結合の存在とは無関係GCの対象になることを確認します。

ユーザーコントロールは、どちらかすぐにクリーンアップしない内部イベントを持っている必要があります、またはそれはVS2010 RCのバグかもしれません。私は、接続を介してこれを報告し、今のContentControlにに切り替えると思います。

あなたは、ユーザーコントロールを使用しているので、

、私はあなたにもGeneric.xamlテンプレートを使用するスイッチにありますと仮定します。これは、切り替えがあまりにも難しいことではない(そしてほとんどの事のためのよりよい解決策である。)

C#でオブジェクトを自動的にすぐに彼らはもはや使用されているよう。

のように「解放」されていません

むしろ、あなたがコントロールからオブジェクトを削除すると、それがなると、のガベージコレクションの対象のその時点で、あなたはそれのUIElementへの他の参照を持っていないと仮定します。

オブジェクトは(何の言及は、アプリケーション内の任意の使用されるオブジェクトから、直接または間接的に、存在しない)「無根」になると、

は、それがコレクションの対象となります。ガベージコレクタそして、最終的には、あなたのオブジェクトをクリーンアップしますが、この問題が発生したとき(一般的に)制御するものではありません。

それは最終的にクリーンアップされますことをするだけの信頼。管理、およびこれの心配は、あなたのために処理されます。

- これは、(一般的におよび.NET)C#の美しさです。 <時間>

編集:いくつかのテストの後、ウィンドウが次のレイアウトパスまでのUIElementへの参照を保持していることが表示されます。あなたがへの呼び出しを追加することによって発生し、これを強制することができます:

this.UpdateLayout();
キャンバス子供から要素を除去した後、

。これは、オブジェクトがGCのために利用できるようになります。

ガベージコレクションの3つの世代があなたのオブジェクトへの参照がないので、場合でも、それはそれらを解放するために3つのガベージコレクションを取ることができる、C#にあります。

第三世代のガベージコレクション、
を強制的に

あなたはGC.Collectを(使用することができます)のパラメータ しかし、最高のapprouchは
、GC.Collect()を自分でコールしないことです 代わりのObservableCollectionにIDisposableインターフェイスとバインド子供を使用 あなたが任意の削除されたオブジェクトのて、CollectionChangedイベントのDispose()を取得するときます。

すこします。また、最近x:名前のマークアップ拡張の店舗への参照UIElementの親制御辞書で鍵付きの文字列名です。

を削除したときにUIElementはその親からの辞書の参照を保持について調査を進めている。

あるブログポスト/ビデオデバッグにメモリリークはこちら コンポーネントのラインナップ x:名前でメモリリーク

このセクションは使用しないでxのの名称又は保管ることによるx:名をクリアしないように消費すぎてメモリーの前部のツリーを収集します。

更新: 登録を解除する名前付きクラスを使用 NameScope

this.grid.Children.Remove(child); // Remove the child from visual tree
NameScope.GetNameScope(this).UnregisterName("child"); // remove the keyed name
this.child = null; // null the field

// Finally it is free to be collected! 

私たちは、同じ問題を抱えていたし、また、これが理由かもしれないと思いました。しかし、我々は、メモリプロファイラツールを使用して私たちのプロジェクトを分析し、Grid.RemoveまたはGrid.RemoveAtとは何の関係もないことがわかりました。私の提案は、ちょうどメモリプロファイラツールで見て、あなたのプロジェクトを持っていると、プロジェクト内で何が起こっているかを見ていると思う私はそう。このことができます期待しています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top