c# 通过内存映射实现文件共享内存的示例代码

内存映射文件是利用虚拟内存把文件映射到进程的地址空间中去,在此之后进程操作文件,就像操作进程空间里的地址一样了,比如使用c语言的 memcpy等内存操作的函数。这种方法能够很好的应用在需要频繁处理一个文件或者是一个大文件的场合,这种方式处理IO效率比普通IO效率要高

共享内存是内存映射文件的一种特殊情况,内存映射的是一块内存,而非磁盘上的文件。共享内存的主语是进程(Process),操作系统默认会给每一 个进程分配一个内存空间,每一个进程只允许访问操作系统分配给它的哪一段内存,而不能访问其他进程的。而有时候需要在不同进程之间访问同一段内存,怎么办 呢?操作系统给出了创建访问共享内存的API,需要共享内存的进程可以通过这一组定义好的API来访问多个进程之间共有的内存,各个进程访问这一段内存就 像访问一个硬盘上的文件一样。而.Net 4.0中引入了System.IO. MemoryMappedFiles命名空间,这个命名空间的类对windows 共享内存相关API做了封装,使.Net程序员可以更方便的使用内存映射文件。

在C#中使用共享内存。以下App1的代码让用户输入一行文本到共享内存中;App2不停的刷新控制台,输出最新的共享内存内容;App3实现的功能和App2相同,但读取方法不同。

App1代码:

using System;
using System.Collections.Generic;android从资源文件中读取文件流显示
using System.Linq;
using System.Text;

using System.IO;

//引用内存映射文件命名空间
using System.IO.MemoryMappedFiles;

namespace App1
{
    class Program
    {
        static void Main(string[] args)
        {
            long capacity = 1<<10<<10;

            //创建或者打开共享内存
            using (var mmf = MemoryMappedFile.CreateOrOpen("testMmf", capacity, MemoryMappedFileAccess.ReadWrite))
            {
                //通过MemoryMappedFile的CreateViewAccssor方法获得共享内存的访问器
                var viewAccessor = mmf.CreateViewAccessor(0, capacity);
                //循环写入,使在这个进程中可以向共享内存中写入不同的字符串值
                while (true)
                {
                    Console.WriteLine("请输入一行要写入共享内存的文字:");

                    string input = Console.ReadLine();

                    //向共享内存开始位置写入字符串的长度
                    viewAccessor.Write(0, input.Length);

                    //向共享内存4位置写入字符
                    viewAccessor.WriteArray<char>(4, input.ToArray(), 0, input.Length);
                }

            }

        }
    }
}

App2代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

//引用使用内存映射文件需要的命名空间
using System.IO.MemoryMappedFiles;

namespace App2
{
    class Program
    {
        static void Main(string[] args)
        {
              long capacity = 1<<10<<10;

              using (var mmf = MemoryMappedFile.OpenExisting("testMmf"))
              {
                  MemoryMappedViewAccessor viewAccessor = mmf.CreateViewAccessor(0, capacity);

                  //循环刷新共享内存字符串的值
                  while (true)
                  {
                      //读取字符长度
                      int strLength = viewAccessor.ReadInt32(0);
                      char[] charsInMMf = new char[strLength];
                      //读取字符
                      viewAccessor.ReadArray<char>(4, charsInMMf, 0, strLength);
                      Console.Clear();
                      Console.Write(charsInMMf);
                      Console.Write("\r");
                      Thread.Sleep(200);
                  }
              }
        }
    }
}

App3代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO.MemoryMappedFiles;
using System.IO;

namespace App3
{
    class Program
    {
        static void Main(string[] args)
        {
            long capacity = 1 << 10 << 10;
            //打开共享内存
            using (var mmf = MemoryMappedFile.OpenExisting("testMmf"))
            {
                //使用CreateViewStream方法返回stream实例
                using (var mmViewStream = mmf.CreateViewStream(0, capacity))
                {
                    //这里要制定Unicode编码否则会出问题
                    using (BinaryReader rdr = new BinaryReader(mmViewStream,Encoding.Unicode))
                    {
                        while (true)
                        {
                            mmViewStream.Seek(0, SeekOrigin.Begin);

                            int length = rdr.ReadInt32();

                            char[] chars = rdr.ReadChars(length);

                            Console.Write(chars);
                            Console.Write("\r");

                            System.Threading.Thread.Sleep(200);
                            Console.Clear();
                        }
                    }
                }
            }
        }
    }
}

在读数据时用了2种方法。

因为在之前很少会用到进程之间的通信,所以此方法只是想初步的认识下。此程序写的过于简陋,有很多东西都没有去判断。比如说是怎么创建了一个共享内存怎么取删除它等等。。。

以上就是c# 通过内存映射实现文件共享内存的示例代码的详细内容,更多关于c# 实现文件共享内存的资料请关注我们其它相关文章!

(0)

相关推荐

  • 详解C#中的System.Timers.Timer定时器的使用和定时自动清理内存应用

    项目比较大有时候会比较卡,虽然有GC自动清理机制,但是还是有不尽人意的地方.所以尝试在项目启动文件中,手动写了一个定时器,定时清理内存,加快项目运行速度. public class Program { [DllImport("psapi.dll")] static extern int EmptyWorkingSet(IntPtr hwProc); //清理内存相关 static void Main() { //启动定时清理内存 SetTimer(); } /// <summar

  • 关于C#调用C++dll传指针释放内存问题

    一.传入dll前,在C#中申请内存空间 c#里面的指针即 IntPtr 申请如下: IntPtr SrcImgData = Marshal.AllocHGlobal(length); 这种需要提前知道空间大小,否则无法确定空间大小,会导致dll内部处理时越界报错. c#里面申请空间了,那么c++里面一般就是在这些空间里面操作了,一般不会重新分配内存,那么就不需要加引用了. c++: uchar* SrcImg c#导入dll函数时申明: IntPtr SrcImg 那么内存释放自然也是由c#来进

  • C#如何快速释放内存的大数组详解

    前言 本文告诉大家如何使用 Marshal 做出可以快速释放内存的大数组.最近在做 3D ,需要不断申请一段大内存数组,然后就释放他,但是 C# 对于大内存不是立刻释放,所以就存在一定的性能问题.在博客园看到了一位大神使用 Marshal 做出快速申请的大数组,于是我就学他的方法来弄一个.本文告诉大家这个类是如何使用. 在使用的时候,先来看下原来的 C# 的大数组性能.可以看到在不停gc,性能不好 static void Main(string[] args) { for (int i = 0;

  • 详解C# Protobuf如何做到0分配内存的序列化

    题目很简单, 就是IMessage对象怎么变成Byte[] 答案1: msg.ToByteArray() 这肯定不符合我们的要求 答案2: using var memoryStream = new MemoryStream(); using var codedOutputStream = new CodedOutputStream(memoryStream); msg.WriteTo(codedOutputStream); codedOutputStream.Flush(); memoryStr

  • c# 从内存中释放Selenium chromedriver.exe

    背景 我设置了一个c#代码来运行Selenium chromedriver.exe.在运行结束时,我有browser.close()来关闭实例.(browser = webdriver.Chrome())我相信它应该从内存中释放chromedriver.exe(我在Windows 7上).但是每次运行后,内存中仍有一个chromedriver.exe实例. 问题窥探 从理论上讲,调用browser.Quit将关闭所有浏览器选项卡并终止进程. 但是,在我的情况下,我无法做到这一点 - 因为我并行运

  • C#托管内存与非托管内存之间的转换的实例讲解

    c#有自己的内存回收机制,所以在c#中我们可以只new,不用关心怎样delete,c#使用gc来清理内存,这部分内存就是managed memory,大部分时候我们工作于c#环境中,都是在使用托管内存,然而c#毕竟运行在c++之上,有的时候,(比如可能我们需要引入一些第三方的c++或native代码的库,在Unity3d开发中很常见)我们需要直接在c#中操纵非托管的代码,这些non-managed memory我们就需要自己去处理他们的申请和释放了, c# 中提供了一些接口,完成托管和非托管之间

  • 详细分析c# 客户端内存优化

    背景概述 C# 开发客户端系统的时候,.net 框架本身就比较消耗内存资源,特别是xp 这种老爷机内存配置不是很高的电脑上运行,所以就需要进行内存上的优化,才能流畅的在哪些低端电脑上运行. 想要对C# 开发的客户端内存优化需要了解以下几个概念. 虚拟内存 这里引用百度百科的概念:虚拟内存是计算机系统内存管理的一种技术.它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换.目前,大多

  • C# 定时器保活机制引起的内存泄露问题解决

    C# 中有三种定时器,System.Windows.Forms 中的定时器和 System.Timers.Timer 的工作方式是完全一样的,所以,这里我们仅讨论 System.Timers.Timer 和 System.Threading.Timer 1.定时器保活 先来看一个例子: class Program { static void Main(string[] args) { Start(); GC.Collect(); Read(); } static void Start() { F

  • 浅谈C# StringBuilder内存碎片对性能的影响

    StringBuilder内部是由多段char[]组成的半自动链表,因此频繁从中间修改StringBuilder,会将原本连续的内存分隔为多段,从而影响读取/遍历性能. 连续内存与不连续内存的性能差,可能高达1600倍. 背景 用StringBuilder的用户可能大都想用StringBuilder拼接html/json模板.组装动态SQL等正常操作.但在一些特殊场景中--如为某种编程语言写语言服务,或者写一个富文本编辑器时,StringBuilder依然也有用武之地,通过里面的Insert/R

  • C#中event内存泄漏总结

    内存泄漏是指:当一块内存被分配后,被丢弃,没有任何实例指针指向这块内存, 并且这块内存不会被GC视为垃圾进行回收.这块内存会一直存在,直到程序退出.C#是托管型代码,其内存的分配和释放都是由CLR负责,当一块内存没有任何实例引用时,GC会负责将其回收.既然没有任何实例引用的内存会被GC回收,那么内存泄漏是如何发生的? 内存泄漏示例 为了演示内存泄漏是如何发生的,我们来看一段代码 class Program { static event Action TestEvent; static void

随机推荐