(精華)2020年9月10日 C#基礎知識點 共享內存(即時通訊)

      網友投稿 793 2025-03-31

      一:內存映射文件

      1.節點通信存在兩種模型:共享內存(Shared memory)和消息傳遞(Messages passing)。

      2.內存映射文件對于托管世界的開發人員來說似乎很陌生,但它確實已經是很遠古的技術了,而且在操作系統中地位相當。實際上,任何想要共享數據的通信模型都會在幕后使用它。

      3.內存映射文件究竟是個什么?內存映射文件允許你保留一塊地址空間,然后將該物理存儲映射到這塊內存空間中進行操作。物理存儲是文件管理,而內存映射文件是操作系統級內存管理。

      優勢:

      1.訪問磁盤文件上的數據不需執行I/O操作和緩存操作(當訪問文件數據時,作用尤其顯著);

      2.讓運行在同一臺機器上的多個進程共享數據(單機多進程間數據通信效率最高);

      利用文件與內存空間之間的映射,應用程序(包括多個進程)可以通過直接在內存中進行讀寫來修改文件。.NET Framework 4 用托管代碼按照本機Windows函數訪問內存映射文件的方式來訪問內存映射文件,管理 Win32 中的內存映射文件 。

      有兩種類型的內存映射文件:

      持久內存映射文件

      持久文件是與磁盤上的源文件關聯的內存映射文件。在最后一個進程使用完此文件后,數據將保存到磁盤上的源文件中。這些內存映射文件適合用來處理非常大的源文件。

      非持久內存映射文件

      非持久文件是未與磁盤上的源文件關聯的內存映射文件。當最后一個進程使用完此文件后,數據將丟失,并且垃圾回收功能將回收此文件。這些文件適用于為進程間通信 (IPC) 創建共享內存。

      1)在多個進程之間進行共享(進程可通過使用由創建同一內存映射文件的進程所指派的公用名來映射到此文件)。

      2)若要使用一個內存映射文件,則必須創建該內存映射文件的完整視圖或部分視圖。還可以創建內存映射文件的同一部分的多個視圖,進而創建并發內存。為了使兩個視圖能夠并發,必須基于同一內存映射文件創建這兩個視圖。

      3)如果文件大于應用程序用于內存映射的邏輯內存空間(在 32 位計算機上為2GB),則還需要使用多個視圖。

      有兩種類型的視圖:流訪問視圖和隨機訪問視圖。使用流訪問視圖可對文件進行順序訪問;在使用持久文件時,隨機訪問視圖是首選方法。

      .Net 共享內存 內存映射文件原理:通過操作系統的內存管理器訪問的,因此會自動將此文件分隔為多個頁,并根據需要對其進行訪問。您不需要自行處理內存管理。如下圖:

      C# .Net 共享內存 演示代碼如下:

      持久內存映射文件:基于現有文件創建一個具有指定公用名的內存映射文件

      using (var mmf = MemoryMappedFile.CreateFromFile(@"c:\內存映射文件.data", FileMode.Open, "公用名")) { //通過指定的 偏移量和大小 創建內存映射文件視圖服務器 using (var accessor = mmf.CreateViewAccessor(offset, length)) //偏移量,可以控制數據存儲的內存位置;大小,用來控制存儲所占用的空間 { //Marshal提供了一個方法集,這些方法用于分配非托管內存、復制非托管內存塊、將托管類型轉換為非托管類型,此外還提供了在與非托管代碼交互時使用的其他雜項方法。 int size = Marshal.SizeOf(typeof(char)); //修改內存映射文件視圖 for (long i = 0; i < length; i += size) { char c= accessor.ReadChar(i); accessor.Write(i, ref c); } } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      //另一個進程或線程可以,在系統內存中打開一個具有指定名稱的現有內存映射文件 using (var mmf = MemoryMappedFile.OpenExisting("公用名")) { using (var accessor = mmf.CreateViewAccessor(4000000, 2000000)) { int size = Marshal.SizeOf(typeof(char)); for (long i = 0; i < length; i += size) { char c = accessor.ReadChar(i); accessor.Write(i, ref c); } } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      非持久內存映射文件:未映射到磁盤上的現有文件的內存映射文件

      using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew("testmap", 10000)) { bool mutexCreated; //進程間同步 Mutex mutex = newMutex(true, "testmapmutex", out mutexCreated); using (var stream = mmf.CreateViewStream()) //創建文件內存視圖流 基于流的操作 { var writer = newBinaryWriter(stream); writer.Write(1); } mutex.ReleaseMutex(); Console.WriteLine("Start Process B and press ENTER to continue."); Console.ReadLine(); mutex.WaitOne(); using (MemoryMappedViewStream stream = mmf.CreateViewStream()) { var reader = newBinaryReader(stream); Console.WriteLine("Process A says: {0}", reader.ReadBoolean()); Console.WriteLine("Process B says: {0}", reader.ReadBoolean()); } mutex.ReleaseMutex(); }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("testmap")) { Mutex mutex = Mutex.OpenExisting("testmapmutex"); mutex.WaitOne(); using (var stream = mmf.CreateViewStream(1, 0))//注意這里的偏移量 { var writer = newBinaryWriter(stream); writer.Write(0); } mutex.ReleaseMutex(); }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      C#共享內存非持久化方式通訊的例子,通訊時的線程和進程控制也沒有問題。如下是實現的代碼。

      先啟動消息服務IMServer_Message,

      再啟動狀態服務IMServer_State,

      IMServer_Message回車一次(創建共享內存公用名和公用線程鎖,并視圖流方式寫共享內存),

      IMServer_State回車一次(獲取共享內存并視圖流方式寫、視圖訪問器寫入結構體類型)

      并立刻IMServer_Message再回車一次(讀取剛剛寫入的信息),

      觀察IMServer_State屏顯變化并等待(線程鎖)約5s(線程鎖被釋放)后

      在IMServer_Message上觀察屏顯(顯示剛剛寫入共享內存的信息)

      IMServer_Message.exe 代碼

      using System; using System.IO; using System.IO.MemoryMappedFiles; using System.Runtime.InteropServices; using System.Threading; namespace IMServer_Message { ///

      /// 用于共享內存方式通信的 值類型 結構體 /// public struct ServiceMsg { public int Id; public long NowTime; } internal class Program { private static void Main(string[] args) { Console.Write("請輸入共享內存公用名(默認:testmap):"); string shareName = Console.ReadLine(); if (string.IsNullOrEmpty(shareName)) shareName = "testmap"; using (MemoryMappedFile mmf = MemoryMappedFile.CreateOrOpen(shareName, 1024000,MemoryMappedFileAccess.ReadWrite)) { bool mutexCreated; //進程間同步 var mutex = new Mutex(true, "testmapmutex", out mutexCreated); using (MemoryMappedViewStream stream = mmf.CreateViewStream()) //創建文件內存視圖流 { var writer = new BinaryWriter(stream); for (int i = 0; i < 5; i++) { writer.Write(i); Console.WriteLine("{0}位置寫入流:{0}", i); } } mutex.ReleaseMutex(); Console.WriteLine("啟動狀態服務,按【回車】讀取共享內存數據"); Console.ReadLine(); mutex.WaitOne(); using (MemoryMappedViewStream stream = mmf.CreateViewStream()) { var reader = new BinaryReader(stream); for (int i = 0; i < 10; i++) { Console.WriteLine("{1}位置:{0}", reader.ReadInt32(), i); } } using (MemoryMappedViewAccessor accessor = mmf.CreateViewAccessor(1024, 10240)) { int colorSize = Marshal.SizeOf(typeof (ServiceMsg)); ServiceMsg color; for (int i = 0; i < 50; i += colorSize) { accessor.Read(i, out color); Console.WriteLine("{1}\tNowTime:{0}", new DateTime(color.NowTime), color.Id); } } mutex.ReleaseMutex(); } Console.WriteLine("測試: 我是 即時通訊 - 消息服務 我啟動啦!!!"); Console.ReadKey(); } } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      IMServer_State.exe代碼

      using System; using System.IO; using System.IO.MemoryMappedFiles; using System.Runtime.InteropServices; using System.Threading; namespace IMServer_State { ///

      /// 用于共享內存方式通信的 值類型 結構體 /// public struct ServiceMsg { public int Id; public long NowTime; } internal class Program { private static void Main(string[] args) { Console.Write("請輸入共享內存公用名(默認:testmap):"); string shareName = Console.ReadLine(); if (string.IsNullOrEmpty(shareName)) shareName = "testmap"; using (MemoryMappedFile mmf = MemoryMappedFile.CreateOrOpen(shareName, 1024000,MemoryMappedFileAccess.ReadWrite)) { Mutex mutex = Mutex.OpenExisting("testmapmutex"); mutex.WaitOne(); using (MemoryMappedViewStream stream = mmf.CreateViewStream(20, 0)) //注意這里的偏移量 { var writer = new BinaryWriter(stream); for (int i = 5; i < 10; i++) { writer.Write(i); Console.WriteLine("{0}位置寫入流:{0}", i); } } using (MemoryMappedViewAccessor accessor = mmf.CreateViewAccessor(1024, 10240)) { int colorSize = Marshal.SizeOf(typeof (ServiceMsg)); var color = new ServiceMsg(); for (int i = 0; i < colorSize*5; i += colorSize) { color.Id = i; color.NowTime = DateTime.Now.Ticks; //accessor.Read(i, out color); accessor.Write(i, ref color); Console.WriteLine("{1}\tNowTime:{0}", new DateTime(color.NowTime), color.Id); Thread.Sleep(1000); } } Thread.Sleep(5000); mutex.ReleaseMutex(); } Console.WriteLine("測試: 我是 即時通訊 - 狀態服務 我啟動啦!!!"); Console.ReadKey(); } } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      (精華)2020年9月10日 C#基礎知識點 共享內存(即時通訊)

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      C# 任務調度

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:在釘釘表格里怎么設置下拉框(表格設定下拉框)
      下一篇:【華為云-建站之路】小白的云“速”建站The road
      相關文章
      亚洲第一成人在线| 中文字幕乱码亚洲精品一区| MM1313亚洲精品无码久久| 亚洲性无码AV中文字幕| 亚洲一区二区三区高清不卡| 久久精品国产亚洲av麻豆图片| 亚洲校园春色小说| 亚洲国产中文在线二区三区免| 亚洲国产精品午夜电影| 亚洲大香人伊一本线| 精品亚洲成在人线AV无码| 亚洲a级在线观看| 久久精品国产亚洲AV忘忧草18| 亚洲第一成人在线| 亚洲欧美日韩中文高清www777| 亚洲日本一线产区和二线| 久久久久亚洲AV无码去区首| 色噜噜的亚洲男人的天堂| 午夜亚洲国产成人不卡在线| 亚洲福利视频一区二区| 亚洲综合区小说区激情区| 亚洲精品少妇30p| 久久精品7亚洲午夜a| 中文字幕亚洲精品| 91亚洲精品麻豆| 亚洲日韩精品国产一区二区三区| 亚洲精品日韩一区二区小说| 含羞草国产亚洲精品岁国产精品| 亚洲AV无码成H人在线观看| 久久久久无码专区亚洲av| 亚洲国产精品无码久久久秋霞2| 亚洲a一级免费视频| 亚洲天堂一区二区三区四区| 国产成人精品日本亚洲网址| 亚洲人成色777777精品| 亚洲国产精品13p| 国产成人A亚洲精V品无码| 亚洲国产日韩一区高清在线| 亚洲欧洲日产专区| 亚洲乱色熟女一区二区三区蜜臀| 伊人久久亚洲综合影院|