zoukankan      html  css  js  c++  java
  • Win2D 入门教程 VB 中文版 防止内存泄漏

    避免内存泄漏

    本文从微软官方文档翻译

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

  • 相关阅读:
    WPF 之 布局(一)
    CSS 之 内层div填充margin,外层div的背景色不会覆盖该margin
    T-SQL 之 多表联合更新
    jQuery
    Joomla, Wordpress, Drupal 全面详细Pk比较-转载
    js ==与===区别(两个等号与三个等号)
    Jquery DataTables 自定义布局sdom
    Jquery DataTable
    解决Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in
    firedebug调试Jquery
  • 原文地址:https://www.cnblogs.com/Nukepayload2/p/win2d_doc_vb_memleak.html
Copyright © 2011-2022 走看看