【问题标题】:Close Unmanaged Resources when WPF Application ClosedWPF 应用程序关闭时关闭非托管资源
【发布时间】:2010-08-13 06:27:21
【问题描述】:

我目前在使用 MVVM WPF 应用程序时遇到了一些问题。在应用程序中,ViewModel 使用 ResourceDictionary 中的 DataTemplate 作为 View 的 DataContext 关联——这样,两个对象都没有对另一个对象的代码内引用。我的 ViewModel 有一个非托管资源,当我的 ViewModel 消失时需要释放它。 (在这种情况下,我的资源是一个使用外部 DLL 的类)

如果我实际上不使用 DLL,当我关闭应用程序时,我的非托管资源的终结器会被调用,它会清理 DLL(我正在实现 IDisposable)。那里一切都很好。

如果我使用 DLL,当我关闭应用程序时,我的资源的终结器不会被调用并且进程不会结束。如果我中断,我可以看到 DLL 在调用 System.Net.Sockets.Socket.Receive() 时被阻塞。我假设正在发生的事情是我的 DLL 以某种方式超过了我的 ViewModel,因此 ViewModel 永远不会被最终确定。

从我读到的内容来看,依赖一个正在完成的对象是一个糟糕的设计——你不能相信 GC。那么,当我想关闭应用程序时,我必须在我的资源上调用 CleanUp() 哪些选项 - 鉴于 View 和 ViewModel 没有相互引用?

编辑:对于一些额外的阅读,这是我参考的关于终结器的blog post

编辑 2:我想出了一个我相当满意的解决方案,所以我想我会为后代添加它并伪关闭这个问题。在应用程序启动时,我为我的应用程序初始化主视图和 ViewModel,因此它是对两者都有引用的一个来源。我在View.Closed 上附加了一个 EventHandler,它触发了我的 ViewModel 上的 CleanUp() 方法,该方法能够在整个应用程序中传播该逻辑。我维护 MVVM 并轻松清理违规资源。

【问题讨论】:

    标签: c# wpf mvvm


    【解决方案1】:

    不,您绝对可以信任 GC。你不能相信那些不是你写的 DLLs 会启动调用 Socket.Receive() 的线程。您必须通过与 DLL 代码的所有者交谈来解决这个问题。如果您实际创建了线程,则将其 IsBackground 属性设置为 true。

    【讨论】:

    • 我尝试在将 IsBackground 设置为 true 的线程上调用 DLL 调用 - 但我仍然遇到同样的问题。我希望如果 UI Dispatcher 无事可做,它可以强制对方停止。
    • +1 用于将 IsBackground 设置为 true(如果您拥有该线程)。您可以依靠 GC 来完成您的对象,但您不能依靠 GC 为您释放对对象的引用。如果您的对象引用了任何其他未处理的对象(事件处理程序很大),那么 GC 将不会删除您的对象。从本质上讲,您仍然可以使用 .NET 出现内存泄漏并耗尽计算机上的所有可用内存,但没有一个可以逃脱您的 AppDomain - 所以当您的应用关闭时,您可以相信 GC 会释放与您的应用关联的所有内存。
    猜你喜欢
    • 2019-12-27
    • 1970-01-01
    • 2010-09-23
    • 1970-01-01
    • 2010-10-01
    • 1970-01-01
    • 2012-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多