WPF用户控件的正确的清除(Proper cleanup of WPF user controls)

2019-07-22 00:17发布

我是比较新的WPF,有些事情它都相当陌生。 其一,不像Windows窗体,WPF控件层次结构不支持IDisposable的。 在Windows窗体,如果用户控件使用任何管理资源,这是很容易通过重写Dispose方法,每一个控件实现清理资源。

在WPF中,这个故事并非如此简单。 我已经寻找这几个小时,遇到了两个基本主题:

第一个主题是微软明确指出,WPF没有实现IDisposable因为WPF控件没有非托管资源。 虽然这可能是真实的,他们似乎已经完全错过了一个事实,即用户扩展到他们的WPF类层次结构可能确实使用管理资源(直接或间接通过一个模型)。 如果不实现IDisposable的,微软已经有效地消除了,才能保证机制,通过自定义WPF控件或窗口中使用非托管资源可以被清理。

第二,我发现Dispatcher.ShutdownStarted几个引用。 我曾尝试使用ShutdownStarted事件,但它似乎不火的每一个控制。 我有一堆,我已经实现了一个处理程序ShutdownStarted WPF UserControl的,而且它永远不会被调用。 我不知道,如果它仅适用于Windows,或者也许是WPF应用程序类。 但是它不能正常发射,而我每次应用程序关闭时泄漏开放的PerformanceCounter对象。

有没有比Dispatcher.ShutdownStarted事件清理非托管资源更好的选择? 有一些技巧,以实现IDisposable接口,使得处置将被调用? 我更希望以避免如果在所有可能使用终结。

Answer 1:

恐怕Dispatcher.ShutdownStarted确实似乎是唯一的机制,WPF提供了在用户控件资财。 (看到一个非常类似的问题 ,我问前一阵子)。

来解决这个问题的另一种方法是(使用MVVM模式时,如视图模型)来移动所有可支配的资源(如果可能的话)从后面的代码,进入单独的类。 然后,在更高层次上,你可以处理你的主窗口关闭,并通过信使类,通知所有的ViewModels。

我很惊讶你没有得到Dispatcher.ShutdownStarted事件。 连接到当时的顶层窗口的用户控件?



Answer 2:

IDisposable接口具有(几乎)WPF下没有意义的,因为机构是从不同的Winforms。 在WPF中,你必须牢记的视觉和逻辑树:这是根本。
因此,任何可视对象通常过着一些其他对象的孩子。 的WPF建筑机构的所述碱是分层地连接视觉对象,然后分离和当它们不破坏有用。

我想你可以检查OnVisualParentChanged因为暴露方法UIElement :这种方法被称为既可以当一个可视对象附加并分离时。 这可能是处置非托管对象(套接字,文件等)在正确的地方。



Answer 3:

我一直在寻找这也和测试型动物选项后,我实现了威尼斯的解决方案

protected override void OnVisualParentChanged(DependencyObject oldParent)
    {
        if (oldParent != null)
        {
            MyOwnDisposeMethod(); //Release all resources here
        }

        base.OnVisualParentChanged(oldParent);
    }

我意识到,当父母打电话Children.Clear()方法,并已经有了加入到儿童用品,DependencyObject的有一个值。 但是,当父母加入的项目( Children.Add(CustomControl)和儿童是空的DependencyObject为空。



Answer 4:

当别人给你关于这个问题的真正有用的信息,还有就是你可能没有将解释很多关于为什么没有了IDisposable的一点点信息。 基本上,WPF(和Silverlight)大量使用在WeakReferences的 - 这可以让你引用一个对象,它的GC仍然可以收集。



文章来源: Proper cleanup of WPF user controls