本通告诉我们哪些使用 Marshal 做出能够便捷释放内部存储器的天数组。

介绍

在选择 Marshal 在此以前须求明白那是哪些,其实 马尔斯hal 就是二个提供 COM
互操作的办法。

澳门凯旋门游戏网址 1

放飞内存

澳门凯旋门注册网址,那么哪些释放内部存款和储蓄器?因为这么些申请是从未经过管理的,若无手动释放,那么就出现内部存款和储蓄器败露。

        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 内部存款和储蓄器,速度神速

澳门凯旋门游戏网址 2

所以在急需开展大数组申请的时候,需求不停释放,就可以利用那些点子。

假设想利用封装好的,请看下边包车型客车大神弄好的类

参见:C#+无unsafe的非托管大数组(large unmanaged array in c# without
‘unsafe’ keyword) – BIT祝威 –
博客园

在利用的时候,先来看下原本的 C#
的大数组品质。可以观察在不停gc,质量不佳

凯旋门074网址,其实运用

骨子里在哪些地点使用?实际上因为十分的多时候都以利用实例化池,但是实例化池在进入游戏的时候,能够让gc不会让程序暂停,不过会在游玩进入下一关的时候,不能飞速清理数据。所以此时就足以采取马尔斯hal 狠抓例化池,须臾间就足以清空。

地点的不二等秘书诀暂且不报告大家如何做,因为涉及到铺子的应用。

本人搭建了本身的博客 先来看下原本的 C。先来看下原本的 C。
应接我们访问,里面有多数新的博客。唯有在本人见到博客写成熟之后才会放在csdn或今日头条,不过就算发表了就不再更新

比如在博客看到有此外不懂的,招待交换,笔者搭建了 dotnet
职业技巧高校
接待大家进入

澳门凯旋门游戏网址 3
本作品使用知识共享签字-非商业性利用-一样格局共享 4.0
国际许可协议开始展览许可。应接转发、使用、重新宣布,但必须保留小说签字林德熙(包罗链接:
),不得用于商业指标,基于本文修改后的文章必须以同样的批准公布。如有任何疑问,请与自身联系。

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

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

先来看下原本的 C。近来在做 3D ,必要不断申请一段大内部存款和储蓄器数组,然后就释放他,不过 C#
对于大内存不是即时释放,所以就存在必然的质量难题。
在知乎看齐了一个人民代表大会神选用 马尔斯hal
做出快捷申请的运气组,于是作者就学他的办法来弄一个。本布告诉大家这些类是怎么样利用

使用

下边选择贰个快捷申请 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 ,可是力不从心接住,软件依旧会崩溃

澳门凯旋门游戏网址 4

相关文章