カスタム コントロールが生成する可能性のあるアンマネージ リソースをクリーンアップする良い方法を見つけようとしています。このシナリオでは、親ウィンドウが、アンマネージ リソースを含むカスタム コントロールを持つ子ウィンドウを開きます (以下のコードを参照)。これらのリソースは、CustomControl が使用されなくなったとき、つまり、それが含まれているツリーがアンロードされたとき (子ウィンドウが閉じたとき)、またはツリーから削除されたとき (つまり、それ自体がアンロードされたとき) にクリーンアップする必要があります。
方法 1 : Unloaded イベント これは、子ウィンドウを手動で閉じたときにトリガーされますが、親ウィンドウを閉じた場合にはトリガーされません (その後、子ウィンドウが自動的に閉じられます)。
メソッド 2 : OnVisualChildrenChanged これは、子ウィンドウが親によって手動または自動で閉じられたときに呼び出されず、CustomControl が別の親要素に移動された場合にのみ使用されます。
方法 3 : Dispatcher.ShutdownStarted ユーザーがアプリを終了する前にいくつかの子ウィンドウを開いたり閉じたりした可能性があり、そのメモリを最後にクリーンアップするだけでは十分ではないため、これはあまり役に立ちません。
方法 4 : CustomControl を ChildWindow.Closing にサブスクライブさせる これも十分ではありません.. コントロールはウィンドウ内にあることを認識する必要はありません。
方法 5 : ファイナライザー が方法 3 と同じ問題に悩まされる.. 呼び出されるまでに時間がかかる可能性がある
public class CustomControlWithManagedResources : Control
{
~CustomControlWithManagedResources()
{
Console.WriteLine("~CustomControlWithManagedResources");
}
public CustomControlWithManagedResources()
{
Unloaded += CustomControl_Unloaded;
Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
}
void Dispatcher_ShutdownStarted(object sender, EventArgs e)
{
Console.WriteLine("ShutdownStarted");
}
void CustomControl_Unloaded(object sender, RoutedEventArgs e)
{
Console.WriteLine("Unloaded");
}
protected override void OnVisualParentChanged(DependencyObject oldParent)
{
base.OnVisualParentChanged(oldParent);
if(oldParent != null)
Console.WriteLine("OnVisualParentChanged");
}
}
public class ChildWindow : Window
{
public ChildWindow()
{
Content = new CustomControlWithManagedResources();
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
protected override void OnMouseDoubleClick(MouseButtonEventArgs e)
{
base.OnMouseDoubleClick(e);
new ChildWindow() { Owner = this }.Show();
}
}