WPF FrameがPageのインスタンスを保持してる件

WPFでページ遷移を作る場合、XAMLでFrameコントロールを置いてナビゲーションするのが手っ取り早い。しかし今回はちょっとした罠に掛かってしまった。

ページ遷移でメモリリーク?

なんか画面移動するたびにメモリが増えていく。まあPageのインスタンスをその都度newしてるので一時的には増えるが、そのうちGCされるだろう。そう思ってたがいつまでも減らない。試しにGC.Collect()してみても減らない。Page内で残ってる参照なども心当たりがない。はて。

犯人はナビゲーション機能

Frameコントロールにはナビゲーションの機能が付いている。NavigationUIVisibility="Visible"を付けると[戻る]とか[進む]のボタンが出てくる。

こういうやつ。見た目がいまいちだしあまり使われてる気はしない。しかしどうもこの[戻る][進む]機能のために、Frameは表示したインスタンスの参照を保持しているようだった。

これはNavigationUIを非表示にしてもやめないし、履歴保持数などのプロパティも設定できない。いったいどの程度持ち続けるのだろうか。まさかメモリが枯渇するまで残し続けることは無いと信じたいが。

対策

前述の通りプロパティなどで無効化することはできないので、履歴を手で消してやる。以下のようなコードをどこかしらに実装する。

while (Frame.CanGoBack)
{
    Frame.RemoveBackEntry();
}

RemoveBackEntry()は最後の履歴を1件削除する。全クリアなどのメソッドは無いらしい。しかも履歴が一件も無い状態で呼ぶと例外が発生する。

これをページ遷移の処理部なりで呼んでやれば、とりあえず延々増えてくことは回避できる。確実なのはFrameの遷移完了イベントあたりか。

しかしAddなんちゃらみたいなメソッドではなく、Content=~という代入でキューイングされるのはちょっとイマイチな実装だと思う。

コメント