Tagged Tags:

本文告诉大家怎么行使 马尔斯hal 做出能够赶快释放内部存款和储蓄器的气数组。

这段时间在做 3D ,供给持续申请一段大内部存款和储蓄器数组,然后就自由他,可是 C#
对于大内部存款和储蓄器不是那时候释放,所以就存在必然的品质难点。
在新浪看齐了一人民代表大会神选择 Marshal
做出飞快申请的运气组,于是作者就学他的法门来弄多个。本公告诉大家这么些类是何等利用

在利用的时候,先来看下原本的 C#
的大数组质量。能够见到在不停gc,质量不佳

图片 1

      static void Main(string[] args)
        {
            for (int i = 0; i < 10000; i++)
            {
                Foo();
            }
            Console.ReadKey();
        }

        private static void Foo()
        {
            var foo = new byte[1000000000];
        }

介绍

在应用 马尔斯hal 此前要求掌握那是何许,其实 马尔斯hal 正是三个提供 COM
互操作的章程。

使用

上面采纳七个高效申请 int 数组来告诉大家如何利用。

是还是不是还记得 C 的报名数组?其实上边包车型地铁点子和 C 的一模二样

            int n = 100000;//长度
            IntPtr buffer = Marshal.AllocHGlobal(sizeof(int) * n);

那时就足以行使 buffer 作为数组

下面前蒙受他的第 k 个因素修改

            IntPtr buffer = Marshal.AllocHGlobal(sizeof(int) * n);
            int k = 2;

            IntPtr t = buffer + k * sizeof(int);
            var p = Marshal.PtrToStructure<int>(t);
            Console.WriteLine("p " + p); //196713 这时的值是不确定

            p = 2;
            Marshal.StructureToPtr(p,t,false);

            p = Marshal.PtrToStructure<int>(t);
            Console.WriteLine("p " + p);//2

            //遍历
            Console.WriteLine("遍历");
            for (int i = 0; i < 10; i++)
            {
                t = buffer + i * sizeof(int);
                Console.WriteLine(Marshal.PtrToStructure<int>(t));
            }

遍历:

            43909312
            44502144
            2
            0
            0
            24
            1357220181
            196712
            550912
            543686656

能够从地点的代码看到,首要行使的八个艺术是 StructureToPtr 和
PtrToStructure ,而 StructureToPtr
正是从钦定项目写到指针,希望大家还掌握怎么着选用指针,PtrToStructure
正是从指针指向的地方发轫读数据,读钦命项目标数额。所以可以从 马尔斯hal
把一个品类应用另一个类型来读取,可是日常必要读取的门类都需借使规定项目大小的,如
char 可以、string 不得以。

转头,StructureToPtr
是对点名指针写入内定的品类,一样也是索要规定那些类其他高低,如能够写入
char 不过不得以写入 string。这正是对数组读写的不二等秘书诀。

那么遍历的时候怎么输出一些无与比伦的值,实际上因为尚未开端化,里面包车型大巴值是不明确的。笔者以为用这些做随机数也不错。

使用 马尔斯hal 是相比安全,因为 ms
做了成都百货上千甩卖,不过也会让程序闪退,如上面包车型客车代码

        private static void Foo()
        {
            int n = 100000;//长度
            IntPtr buffer = Marshal.AllocHGlobal(sizeof(int) * n);

            try
            {
                var t = buffer + (n * 10) * sizeof(int);
                var p = Marshal.PtrToStructure<int>(t);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }

            Marshal.FreeHGlobal(buffer);
        }

会出现万分 System.AccessViolationException,这一个那些是力不胜任 catch
的,所以选择的时候最棒封装一下

“System.AccessViolationException”类型的未经处理的异常在 未知模块
尝试读取或写入受保护的内存。这通常指示其他内存已损坏

对于大内部存款和储蓄器不是即时释放。倘使急需 catch 那么请在 app.config 增添下边的代码

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <legacyCorruptedStateExceptionsPolicy enabled="true" />
  </runtime>
</configuration>

然后在 Main 函数增加 HandleProcessCorruptedStateExceptions ,请看代码

        [HandleProcessCorruptedStateExceptions]
        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

            for (int i = 0; i < 100000; i++)
            {
                try
                {
                    Foo();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);

                }
            }
            Console.WriteLine("完成");
            Console.ReadKey();
        }

对于大内部存款和储蓄器不是即时释放。此时能够见见步向 UnhandledException ,可是无计可施接住,软件依然会崩溃

图片 2

获释内部存储器

那么怎么着释放内存?因为这么些申请是尚未经过管理的,若无手动释放,那么就涌出内部存款和储蓄器败露。

        static void Main(string[] args)
        {
            for (int i = 0; i < 10000; i++)
            {
                Foo();
            }
            Console.ReadKey();
        }

        private static void Foo()
        {
            int n = 100000;//长度
            IntPtr buffer = Marshal.AllocHGlobal(sizeof(int) * n);

        }

地点的代码相当的慢就能够看见内部存款和储蓄器占用到2G,所以必要手动释放

            Marshal.FreeHGlobal(buffer);

原来的 byte 数组需求使用 1G 内部存款和储蓄器,何况速度非常慢,而现行反革命采纳那些格局只须要7M 内部存款和储蓄器,速度赶快

图片 3

对于大内部存款和储蓄器不是即时释放。就此在急需张开大数组申请的时候,必要不停释放,就能够运用这一个措施。

倘若想使用封装好的,请看下边包车型的士大神弄好的类

参见:C#对于大内部存款和储蓄器不是即时释放。+无unsafe的非托管大数组(large unmanaged array in c#对于大内部存款和储蓄器不是即时释放。 without
‘unsafe’ keyword) – BIT祝威 –
博客园

实际上利用

其实在哪些地方使用?实际上因为众多时候都以行使实例化池,但是实例化池在步入娱乐的时候,能够让gc不会让程序暂停,但是会在玩耍步向下一关的时候,不可能飞速清理数据。所以此时就足以行使
马尔斯hal 压实例化池,眨眼间间就可以清空。

地点的方法一时半刻不告知大家如何是好,因为涉嫌到小卖部的采取。

本人搭建了和煦的博客
款待我们访谈,里面有成百上千新的博客。独有在本人来看博客写成熟之后才会放在csdn或新浪,可是假若公布了就不再更新

若果在博客见到有任何不懂的,应接调换,小编搭建了 dotnet
职业才具高校
招待我们到场

图片 4
本作品使用知识分享署名-非商业性利用-同样形式分享 4.0
国际许可协议开展许可。招待转载、使用、重新发表,但不能够不保留小说签名林德熙(包蕴链接:
),不得用于生意指标,基于本文修改后的小说必得以同样的批准发布。如有任何疑问,请与自己联系。

发表评论

电子邮件地址不会被公开。 必填项已用*标注