避免内存泄漏

本文从微软官方文档翻译

http://microsoft.github.io/Win2D/html/RefCycles.htm

如果文档有问题,可以在 https://github.com/Nukepayload2/Win2dDocVB发 Issue,也可以直接回复。

当在托管的 XAML 应用程序中使用 Win2D 控件,需要注意垃圾回收器回收这些控件前它们的引用计数循环。

你有一个问题,如果...

您正在使用 Win2D 从一种.NET 语言如 VB (不是 c + +)

您使用 Win2D XAML 控件之一:

l  CanvasControl

l  CanvasVirtualControl

l  CanvasAnimatedControl

l  CanvasSwapChainPanel

l  你订阅 Win2D 控件的事件 (例如 绘制,CreateResources,SizeChanged...)

l  您的应用程序多个 XAML 页之间来回移动

如果满足所有这些条件,引用计数循环将阻止 Win2D 控件被垃圾回收。新的 Win2D 资源分配每次应用程序移动到一个不同的页,但旧的永远不会被释放,所以内存泄漏。要避免此问题,必须添加代码来显式地打破这种循环。

如何修复它

打破引用计数循环,让你的页面进行垃圾回收:

处理Xaml页面或对话框的Unloaded事件

在卸载处理程序,调用 RemoveFromVisualTree Win2D 控件并释放 (通过设置为 Nothing) 对 Win2D 控件的任何显式引用

示例代码:

VB

    Private Sub page_Unloaded(sender As Object, e As RoutedEventArgs) Handles Me.Unloaded

        Me.canvas.RemoveFromVisualTree

        Me.canvas = Nothing

    End Sub

如何测试内存是否泄漏

若要测试是否您的应用程序正确打破引用循环,将代码添加到包含 Win2D 控件的任何 XAML 页或对话框的终结器方法:

VB

    Protected Overrides Sub Finalize()

        Debug.WriteLine("回收画布")

        MyBase.Finalize()

    End Sub

在您的应用程序的构造函数建立一个计时器,它将使确定垃圾收集发生在固定的时间间隔:

VB

    Dim gcTimer As New DispatcherTimer

    AddHandler gcTimer.Tick, Sub() GC.Collect

    gcTimer.Interval = TimeSpan.FromSeconds()

    gcTimer.Start

导航到页面,然后从它到其他页面上。

引用循环打破后大概一秒你会在输出窗口看到 "回收画布"

请注意,调用 GC.Collect 会影响性能,所以您应该在测试后删除此测试代码

残酷的细节

对象 A 引用了 B,同时 B 也引用 A.

这时发生一个循环。或者当 B 和 B 的引用引用 C,而 C 引用 A 等。

当订阅事件的 XAML 控件,这种循环是几乎不可避免:

l  XAML 页保留对它所包含的所有控件的引用

l  控件保持对已订阅它们的事件处理程序委托的引用

l  每个委托保存到其目标实例的引用

l  事件处理程序通常是实例方法的 XAML 页类,所以他们目标实例引用点返回到 XAML 页面,创建一个循环

如果在.NET 中实现所有涉及的对象,这种循环不是问题因为.NET 垃圾回收,垃圾回收算法能够识别并回收的对象组,即使它们链接在一个循环中。与.NET不同的是 c + + 管理内存的引用计数,无法检测和回收循环对象。尽管有这种限制,使用 Win2D 的 c + + 应用程序没有任何问题,因为 c + + 事件处理程序默认为弱引用而不是他们的目标实例的强引用。因此页面引用该控件,而控件引用的事件处理程序委托,此委托未引用返回到页面,所以没有任何这种问题。

问题在于当.NET 应用程序使用 c + + WinRT 组件如 Win2D:

l  XAML 页是应用程序的一部分,所以使用垃圾回收

l  Win2D 控制在 c + + 中实现,因此,使用引用计数

l  事件处理程序委托是应用程序的一部分,所以使用垃圾回收,认为对其目标实例的强引用

一个引用循环是存在的但参加这个的 Win2D 对象不使用.NET 垃圾回收。这意味着垃圾收集器是无法看到整个链,因此它不能检测或回收的对象。当这发生时,应用程序必须通过显式打破循环帮忙。这可以通过释放所有引用从页面到控件 (如上文所建议) 或通过都释放从控制到可能指向页面 (使用页卸载事件取消订阅所有事件处理程序) 的事件处理程序委托的所有引用。

Win2D 入门教程 VB 中文版 - 防止内存泄漏的更多相关文章

  1. Win2D 入门教程 VB 中文版

    继续填坑!又一个c#教程变为vb! 这是我翻译的Win2D教程,链接保留了微软原版的. 如果文档有问题,可以在 https://github.com/Nukepayload2/Win2dDocVB发 ...

  2. Win2D 官方文章系列翻译 - 避免内存泄漏

    本文为个人博客备份文章,原文地址: http://validvoid.net/win2d-avoiding-memory-leaks/ 在托管 XAML 应用中使用 Win2D 控件时,必须谨慎处理对 ...

  3. UWP开发入门(十六)——常见的内存泄漏的原因

    本篇借鉴了同事翔哥的劳动成果,在巨人的肩膀上把稿子又念了一遍. 内存泄漏的概念我这里就不说了,之前<UWP开发入门(十三)——用Diagnostic Tool检查内存泄漏>中提到过,即使有 ...

  4. JavaScript学习总结(二十三)——JavaScript 内存泄漏教程

    参考教程:http://www.ruanyifeng.com/blog/2017/04/memory-leak.html 一.什么是内存泄漏? 程序的运行需要内存.只要程序提出要求,操作系统或者运行时 ...

  5. 教程2:如何找到内存泄漏dotmemory

    在本教程中,我们将看到如何使用dotmemory定位和固定在你的应用程序的内存泄漏.但在开始之前,让我们在一个内存泄漏是一致的. 内存泄漏是什么? 根据维基百科,内存泄漏是由于不正确的内存管理时,”一 ...

  6. UWP开发入门(十三)——用Diagnostic Tool检查内存泄漏

    因为.NET的垃圾回收机制相当完善,通常情况下我们是不需要关心内存泄漏的.问题人一但傻起来,连自己都会害怕,几个页面跳啊跳的,内存蹭蹭的往上涨,拉都拉不住.这种时候我们就需要冷静下来,泡一杯热巧克力. ...

  7. Android内存管理(5)*官方教程:Logcat内存日志各字段含义,查看当前内存快照,跟踪记录内存分配,用adb查看内存情况时各行列的含义,捕获内存快照的3种方法,如何让程序暴漏内存泄漏的方法

    Investigating Your RAM Usage In this document Interpreting Log Messages                 内存分析日志中各消息的含 ...

  8. autofac生命周期入门(如何避免内存泄漏)

    如果你是一个IOC新手,那么生命周期可能会比较难以理解.以至于谈到这个问题时,一些老手也时常表示疑虑和害怕.一个令人不安的问题就是-对象没有在合适的时机被销毁.这样一来内存的使用率就会一直攀升,直到程 ...

  9. JavaScript 内存泄漏教程

    一.什么是内存泄漏? 程序的运行需要内存.只要程序提出要求,操作系统或者运行时(runtime)就必须供给内存. 对于持续运行的服务进程(daemon),必须及时释放不再用到的内存.否则,内存占用越来 ...

随机推荐

  1. cassandra在服务端像leveldb一样进行插入初试成功

    经过研究,决定在 cql3/QueryProcessor.java 里面下手. 这里有两个函数,第一个是 public ResultMessage process(String queryString ...

  2. 【转】设置cocos2dx 屏幕分辨率

    [转载连接:]http://www.cnblogs.com/onlycxue/p/3500026.html 做手机上的软件首先要考虑的就是屏幕分辨率怎么解决.coco2dx已经有了很好的解决方法. 用 ...

  3. 整体二分 HDU - 5808

    题目大意 有n个物品,排成一个序列,每个物品有一个di表示取到i要走的距离,vi表示i的价值. 给m组询问[l,r] ,c,sum,问由[l,r]的di<=c的物品能否凑出sum的价值(每个物品 ...

  4. C++ 多项目dll调用-隐式

    将DAA人脸检测做成动态库以便其他程序调用,采用隐式调用完成. 给出部分关于dll制作的关键代码: 1.DLL 多项目DLL编写注意将其他相关项目设置成静态库,以及各库涉及的版本一致性. DLL.h ...

  5. Oracle中插入100万条数据

    在做项目的工程中,需要数据库中存在大量的数据进行程序的验证,但是我们又没有数据,这时就需要我们自己手动建一个表,插入大量数据,进行验证. 那么插入大量数据的sql语句如下: insert into E ...

  6. [WPF自定义控件库] 自定义控件的代码如何与ControlTemplate交互

    1. 前言 WPF有一个灵活的UI框架,用户可以轻松地使用代码控制控件的外观.例设我需要一个控件在鼠标进入的时候背景变成蓝色,我可以用下面这段代码实现: protected override void ...

  7. Bid和Ask

    一直很懵到底哪个是哪个,记吧,很快就又懵了.网上又坑,每一个解释清楚的.这次搞明白了记下来. 当然,这么逗比的取名法我也是醉了.直接加点东西,UserBuy,UserSell,BankBuy,Bank ...

  8. IT兄弟连 JavaWeb教程 请求转发案例

    CheckServlet类与OutputServlet类之间为请求转发关系.在web.xml文件中,为CheckServlet映射的URL为"/check",为OutputServ ...

  9. iperf工具学习记录

    源码下载地址:http://sourceforge.net/projects/iperf/ 编译命令: tar -zxvf iperf-2.0.5.tar.gz cd iperf-2.0.5 ./co ...

  10. 自己写一个websocket

    import socket, base64, hashlib sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsock ...