いつも、お世話になっております。
親ウィンドウから子ウィンドウを開き、子ウィンドウが開かれた時点でImageコントロールを複数作成して子ウィンドウに配置したいと思っております。
配置する複数のImageコントロールは、開かれる度にPathや数が変化し、コードビハインド側で操作したいので、コードビハインド側で配置しています。
問題点
(1)子ウィンドウを閉じた際に、Imageコントロールが解放されずメモリ上に残ってしまう。
(2)そのため、子ウィンドウを閉じる→開くを繰り返した際に、メモリに蓄積されてしまう。
試してみたこと
・子ウィンドウのClosingイベントでGC.Collect();
を行う。
親 起動時 55MB
子 起動 81MB
子 終了 78MB
子 起動 103MB
子 終了 78MB
子 起動 103MB
子 終了 78MB
このように子ウィンドウ初回終了時は、メモリが解放されることはなく、
2回目以降は、ほぼきちんとメモリ解放できていますが、稀に解放できないときがあります。
質問
・ウィンドウ終了時にImageコントロールを確実に破棄する方法を教えていただきたいです。
・なぜ初回終了時はメモリが解放されないのでしょうか。(子ウィンドウのInstanceプロパティあたりの実装方法に問題があるのでしょうか?)
環境
C#, .NET 4.6, VS2017 Pro
コード
親Windowからはvar cw = ChildWindow.Instance; cw.Show(); cw.Owner = this;
このように開いています。
C#
1 public partial class ChildWindow: Window 2 { 3 #region ユニークなウィンドウ プロパティ 4 private static ChildWindow _instance; 5 6 public static ChildWindow Instance 7 { 8 get 9 { 10 if (_instance == null || !_instance.IsLoaded) 11 { 12 _instance = new ChildWindow(); 13 } 14 15 return _instance; 16 } 17 } 18 #endregion 19 20 private ObservableCollection<Image> Images; 21 private ObservableCollection<string> PathList { get; } = new ObservableCollection<string> 22 { 23 @"test0.JPG", 24 @"test1.JPG", 25 @"test2.JPG", 26 @"test3.JPG" 27 }; 28 29 public ChildWindow() 30 { 31 InitializeComponent(); 32 33 Images = new ObservableCollection<Image>(); 34 foreach (var p in PathList) 35 { 36 Images.Add(CreateImage(p)); 37 } 38 39 foreach (var i in Images) 40 { 41 grid.Children.Add(i); 42 } 43 44 this.Closing += (s, e) => 45 { 46 // あまり意味はないかもしれません 47 foreach (var i in Images) 48 { 49 grid.Children.Remove(i); 50 } 51 52 GC.Collect(); 53 }; 54 } 55 56 private Image CreateImage(string path) 57 { 58 Image img = new Image(); 59 img.Visibility = Visibility.Collapsed; 60 61 using (FileStream stream = File.OpenRead(path)) 62 { 63 BitmapImage bi = new BitmapImage(); 64 bi.BeginInit(); 65 bi.StreamSource = stream; 66 bi.CacheOption = BitmapCacheOption.OnLoad; 67 bi.CreateOptions = BitmapCreateOptions.None; 68 bi.DecodePixelHeight = 1000; 69 bi.EndInit(); 70 bi.Freeze(); 71 72 img.Source = bi; 73 } 74 75 return img; 76 } 77 }
ChildWindowのXAMLは<Grid Name="grid"/>のみです。
回答3件
あなたの回答
tips
プレビュー