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

作者:zls365 时间:2023-03-02 12:15:35 

内存映射文件是利用虚拟内存把文件映射到进程的地址空间中去,在此之后进程操作文件,就像操作进程空间里的地址一样了,比如使用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种方法。

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

来源:https://mp.weixin.qq.com/s/RIozylOT3tGodyKgCZHpAA

标签:c#,内存映射,共享内存
0
投稿

猜你喜欢

  • Android开发:微信授权登录与微信分享完全解析

    2023-03-20 14:08:10
  • Java中this,static,final,const用法详解

    2022-01-23 17:21:41
  • C#设置自定义文件图标实现双击启动(修改注册表)

    2023-08-21 08:43:46
  • Spring Security认证机制源码层探究

    2022-07-27 19:05:26
  • Spring-Security实现登录接口流程

    2023-03-24 05:35:40
  • Java实现五子棋游戏

    2022-07-08 12:50:27
  • java后端解决跨域的几种问题解决

    2022-01-05 06:34:24
  • C# 动态调用WebService的示例

    2023-07-04 05:40:20
  • C# Chart折线图使用鼠标滚轮放大、缩小和平移曲线方式

    2022-09-01 07:07:39
  • Android实现双击返回键退出应用实现方法详解

    2023-03-23 21:33:29
  • Maven中央仓库发布的实现方法

    2023-12-09 07:15:06
  • Java中后台线程实例解析

    2022-01-05 06:45:08
  • C语言简明讲解变量的属性

    2021-06-23 17:45:28
  • Android实现通话自动录音

    2021-08-29 20:33:35
  • 全面理解Java类和对象

    2021-11-17 11:11:50
  • C#实现简单聊天程序的方法

    2022-01-02 22:31:20
  • Java中使用HashMap时指定初始化容量性能解析

    2023-01-01 11:05:27
  • Java NIO实现聊天功能

    2022-06-12 08:31:31
  • C#线程同步的三类情景分析

    2023-01-07 22:38:04
  • Java+Swing实现医院管理系统的完整代码

    2023-03-17 00:40:21
  • asp之家 软件编程 m.aspxhome.com