Wpf管理资源清理

时间:2014-04-20 19:47:40

标签: wpf dispose unmanagedresources

我试图找到一种清理自定义控件可能生成的非托管资源的好方法。该场景是父窗口打开一个子窗口,该窗口具有带有非托管资源的自定义控件(请参阅下面的代码)。当CustomControl不再使用时,即当它所在的树被卸载(即子窗口关闭),或者从树中移除它(即它本身被卸载)时,需要清理这些资源

方法1:卸载事件 当您手动关闭子窗口时会触发此操作,但如果关闭父窗口(然后自动关闭子窗口)则不会触发此窗口

方法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();
    }
}

2 个答案:

答案 0 :(得分:2)

在WPF应用程序中执行此操作的正确方法是使用MVVM模式并从View(控件)和ViewModel中删除所有逻辑和依赖项。

您的父ViewModel将创建一个实现IDisposable的子ViewModel,然后当它删除子ViewModel时,它将在子ViewModel上调用Dispose

如果您的主ViewModel具有需要清理的非托管资源,那么它应该实现IDisposable并且创建它的引导程序应该负责清理它们。

另一个好的参考是Caliburn.Micro

答案 1 :(得分:1)

您似乎要求结束活动。

看看这个:

http://msdn.microsoft.com/en-us/library/system.windows.window_events(v=vs.110).aspx

当一个窗口关闭时,它会引发两个事件:Closing和Closed。

虽然可以通过非客户端和客户端区域中提供的机制显式关闭窗口,但是由于应用程序或Windows的其他部分中的行为,窗口也可以隐式关闭,包括以下内容:

用户注销或关闭Windows。

窗口所有者关闭(请参阅所有者)。

主应用程序窗口关闭,ShutdownMode为OnMainWindowClose。

调用关机。

在所有这些场景中,将会调用Closing和Close事件。

不要将您的控件订阅到Window.Closing事件。让窗口完成工作。