Apparent memory leak in DockingManager

オープン 初心者向け
#1,812 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
72/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
活発
技術スタック
csharp
領域
desktop

調査の方向性

まずDockingManagerのコードにあるCollectLayoutItemsDeleted、RemoveDocumentLayoutItem、LayoutItem.Detach()を読んでください。LayoutAnchorable項目を追加して閉じるという報告されたループを再現し、閉じた項目が_layoutItemsと_logicalChildrenから削除され、回収可能かどうかを確認してください。ドキュメントのクリーンアップを壊すことなくリークが修正されれば完了です。

索引モデルが issue の本文から書いたものです。

説明

An application is set up with a DockingManager in xaml like

<UserControl
    x:Class="Test.MainDockingContentContainer"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:xcad="clr-namespace:Xceed.Wpf.AvalonDock;assembly=Xceed.Wpf.AvalonDock"
    xmlns:layout="clr-namespace:Xceed.Wpf.AvalonDock.Layout;assembly=Xceed.Wpf.AvalonDock">
  <Grid>
    <xcad:DockingManager x:Name="DockManager">
      <layout:LayoutRoot>
        <layout:LayoutPanel Orientation="Horizontal">
          <layout:LayoutAnchorablePaneGroup Orientation="Vertical">
            <layout:LayoutAnchorablePane x:Name="A" DockHeight="0.7*"/>
            <layout:LayoutAnchorablePane x:Name="B" DockHeight="0.3*" />
          </layout:LayoutAnchorablePaneGroup>
        </layout:LayoutPanel>
      </layout:LayoutRoot>
    </xcad:DockingManager>
  </Grid>
</UserControl>

and code-behind which is equivalent to

partial MainDockingContentContainer()
{
  InitializeComponent()
  A.Name = "A";
  B.Name = "B";
}

this gets used to add/remove content in code, essentially like this:

var testPane = mainDock.DockManager.Layout.Descendents().OfType<LayoutAnchorablePane>().Where( l => l.Name == "A" ).FirstOrDefault();
for( var i = 0 ; i < 20 ; i++ )
{
  var testWin = new LayoutAnchorable { Content = new System.Windows.Controls.TextBlock { Text = "content" } };
  testPane.Children.Add( testWin );
  testWin.Show();
  testWin.Close();
}

The result of this is that after this loop ran testPane.Children is empty as expected, but

  • DockingManager._layoutItems still contains 20 LayoutAnchorableItem
  • that LayoutAnchorableItem's LayoutElement still is set to testWin (though its Root is null), and its Model still set to the TextBlock
  • both can never get garbage collected so in an actual application causes severe leaks, plus _layoutItems grows bigger and bigger
  • similar issue exists for DockingManager._logicalChildren

In other words: even though the LayoutAnchorable was closed indicating the caller doesn't need it anymore, it remains in memory forever. I first thought perhaps what I'm doing is not intended usage (but if not Close, what else would have to be used?) but on further inspection I think it's an oversight: core issue seems to be that the LayoutItem.Detach() method (which is responsible for clearing LayoutElement and Model) never gets called. I also see no code in DockingManager which does that, whereas that should probably be the place where it should happen; also because there is already CollectLayoutItemsDeleted and and which does

      LayoutItem[] array = _layoutItems.Where( ( LayoutItem item ) => item.LayoutElement.Root != Layout ).ToArray();
      for( int i = 0 ; i < array.Count() ; i++ )
      {
        LayoutItem layoutItem = array[ i ];
        RemoveDocumentLayoutItem( layoutItem.LayoutElement as LayoutDocument );
      }

and RemoveDocumentLayoutItem is

    LayoutItem layoutItem = _layoutItems.FirstOrDefault( ( LayoutItem item ) => item.LayoutElement == contentToRemove );
    if( layoutItem != null )
    {
      layoutItem._ClearDefaultBindings();
      layoutItem.Detach();
      _layoutItems.Remove( layoutItem );
      if( contentToRemove != null && contentToRemove.Content != null && contentToRemove.Content is UIElement )
      {
        InternalRemoveLogicalChild( contentToRemove.Content );
      }
    }

So I guess what is missing here is there is actually nothing specific to LayoutDocument in RemoveDocumentLayoutItem, it just looks up LayoutItem, and simply removing as LayoutDocument fixes the issue?

主要言語
C#
スター
4.2k
フォーク
907
PR マージ指標
30日以内にマージされた PR はありません

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

xceedsoftware/wpftoolkit のほかの issue

xceedsoftware/wpftoolkit の issue をすべて見る

似ている issue

C# の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。