我正在尝试找到一种清理自定义控件可能生成的非托管资源的好方法。该场景是父窗口打开一个子窗口,该子窗口具有带有非托管资源的自定义控件(请参见下面的代码)。当 CustomControl 不再使用时,即当它所在的树被卸载(即子窗口关闭)或从树中移除(即它本身被卸载)时,需要清理这些资源
方法1:卸载事件 当您手动关闭子窗口时触发,但如果您关闭父窗口(然后自动关闭子窗口)则不会触发
方法 2:OnVisualChildrenChanged 当子窗口手动或由父级自动关闭时不会调用此方法,并且仅在将 CustomControl 移动到不同的父元素时使用。
方法 3:Dispatcher.ShutdownStarted 这并没有太大帮助,因为用户可能在完成应用程序之前已经打开/关闭了几个子窗口,并且仅在最后清理内存还不够好。
方法 4:让 CustomControl 订阅 ChildWindow.Closing 这也不够好,.. 控件不必知道它在窗口中。
方法 5:Finalizer 遇到与方法 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();
}
}