zoukankan      html  css  js  c++  java
  • C# 进程间通信(共享内存)

    进程间通信的方式有很多,常用的方式有:

      1.共享内存(内存映射文件,共享内存DLL)。

      2.命名管道和匿名管道。

      3.发送消息 

    本文是记录共享内存的方式进行进程间通信,首先要建立一个进程间共享的内存地址,创建好共享内存地址后,一个进程向地址中写入数据,另外的进程从地址中读取数据。

    在数据的读写的过程中要进行进程间的同步。

    进程间数据同步可以有以下的方式

      1. 互斥量Mutex

      2. 信号量Semaphore

      3. 事件Event 

    本文中进程间的同步采用 信号量Semaphore的方式同步思想类似于操作系统中生产者和消费者问题的处理方式。

    在A进程中创建共享内存,并开启一个线程用来读取B进程向共享内存中写入的数据,定义两个信号量进行读写互斥同步 

    A进程中的程序代码

    Using system;

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.Data;

    using System.Drawing;

    using System.Linq;

    using System.Text;

    using System.Windows.Forms;

    using System.Runtime.InteropServices;

    using System.Threading;

    using System.Diagnostics;

    namespace AppOne

    {

        public partial class AppOneMain : Form

        {

            const int INVALID_HANDLE_VALUE = -1;

            const int PAGE_READWRITE = 0x04;

            [DllImport("User32.dll")]

            private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);

            [DllImport("User32.dll")]

            private static extern bool SetForegroundWindow(IntPtr hWnd);

            //共享内存

            [DllImport("Kernel32.dll", EntryPoint = "CreateFileMapping")]

            private static extern IntPtr CreateFileMapping(IntPtr hFile, //HANDLE hFile,

             UInt32 lpAttributes,//LPSECURITY_ATTRIBUTES lpAttributes,  //0

             UInt32 flProtect,//DWORD flProtect

             UInt32 dwMaximumSizeHigh,//DWORD dwMaximumSizeHigh,

             UInt32 dwMaximumSizeLow,//DWORD dwMaximumSizeLow,

             string lpName//LPCTSTR lpName

             );

            [DllImport("Kernel32.dll", EntryPoint = "OpenFileMapping")]

            private static extern IntPtr OpenFileMapping(

             UInt32 dwDesiredAccess,//DWORD dwDesiredAccess,

             int bInheritHandle,//BOOL bInheritHandle,

             string lpName//LPCTSTR lpName

             );

            const int FILE_MAP_ALL_ACCESS = 0x0002;

            const int FILE_MAP_WRITE = 0x0002;

            [DllImport("Kernel32.dll", EntryPoint = "MapViewOfFile")]

            private static extern IntPtr MapViewOfFile(

             IntPtr hFileMappingObject,//HANDLE hFileMappingObject,

             UInt32 dwDesiredAccess,//DWORD dwDesiredAccess

             UInt32 dwFileOffsetHight,//DWORD dwFileOffsetHigh,

             UInt32 dwFileOffsetLow,//DWORD dwFileOffsetLow,

             UInt32 dwNumberOfBytesToMap//SIZE_T dwNumberOfBytesToMap

             );

            [DllImport("Kernel32.dll", EntryPoint = "UnmapViewOfFile")]

            private static extern int UnmapViewOfFile(IntPtr lpBaseAddress);

            [DllImport("Kernel32.dll", EntryPoint = "CloseHandle")]

            private static extern int CloseHandle(IntPtr hObject);

            private Semaphore m_Write;  //可写的信号

            private Semaphore m_Read;  //可读的信号

            private IntPtr handle;     //文件句柄

            private IntPtr addr;       //共享内存地址

            uint mapLength;            //共享内存长

            //线程用来读取数据        

            Thread threadRed;

            public AppOneMain()

            {

                InitializeComponent();

                init();

            }   

           // 初始化共享内存数据 创建一个共享内存

            privatevoid init()

            {

                m_Write = new Semaphore(1, 1, "WriteMap");//开始的时候有一个可以写

                m_Read = new Semaphore(0, 1, "ReadMap");//没有数据可读

                mapLength = 1024;

                IntPtr hFile = new IntPtr(INVALID_HANDLE_VALUE);

                handle = CreateFileMapping(hFile, 0, PAGE_READWRITE, 0, mapLength, "shareMemory");

                addr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);

                //handle = OpenFileMapping(0x0002, 0, "shareMemory");

                //addr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);

                threadRed = new Thread(new ThreadStart(ThreadReceive));

                threadRed.Start();

            }

           // 线程启动从共享内存中获取数据信息

            private void ThreadReceive()

            {

                myDelegate myI = new myDelegate(changeTxt);

                while (true)

                {

                    try

                    {

                        //m_Write = Semaphore.OpenExisting("WriteMap");

                        //m_Read = Semaphore.OpenExisting("ReadMap");

                        //handle = OpenFileMapping(FILE_MAP_WRITE, 0, "shareMemory");

                        //读取共享内存中的数据:

                        //是否有数据写过来

                        m_Read.WaitOne();

                        //IntPtr m_Sender = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);

                        byte[] byteStr = new byte[100];

                        byteCopy(byteStr, addr);

                        string str = Encoding.Default.GetString(byteStr, 0, byteStr.Length);

                       /////调用数据处理方法 处理读取到的数据

                        m_Write.Release();

                    }

                    catch (WaitHandleCannotBeOpenedException)

                    {

                        continue;

                        //Thread.Sleep(0);

                    }

                 }

             }

            //不安全的代码在项目生成的选项中选中允许不安全代码

            static unsafe void byteCopy(byte[] dst, IntPtr src)

            {

                fixed (byte* pDst = dst)

                {

                    byte* pdst = pDst;

                    byte* psrc = (byte*)src;

                    while ((*pdst++ = *psrc++) != '')

                        ;

                }

             }

         }

    }

    B进程向共享内存中写入的数据

    using System;

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.Data;

    using System.Drawing;

    using System.Linq;

    using System.Text;

    using System.Windows.Forms;

    using System.Runtime.InteropServices;

    using System.Threading;

    namespace AppTwo

    {

        public partial class AppTwoMain : Form

        {

            const int INVALID_HANDLE_VALUE = -1;

            const int PAGE_READWRITE = 0x04;

            //共享内存

            [DllImport("Kernel32.dll", EntryPoint = "CreateFileMapping")]

            private static extern IntPtr CreateFileMapping(IntPtr hFile, //HANDLE hFile,

             UInt32 lpAttributes,//LPSECURITY_ATTRIBUTES lpAttributes,  //0

             UInt32 flProtect,//DWORD flProtect

             UInt32 dwMaximumSizeHigh,//DWORD dwMaximumSizeHigh,

             UInt32 dwMaximumSizeLow,//DWORD dwMaximumSizeLow,

             string lpName//LPCTSTR lpName

             );

            [DllImport("Kernel32.dll", EntryPoint = "OpenFileMapping")]

            private static extern IntPtr OpenFileMapping(

             UInt32 dwDesiredAccess,//DWORD dwDesiredAccess,

             int bInheritHandle,//BOOL bInheritHandle,

             string lpName//LPCTSTR lpName

             );

            const int FILE_MAP_ALL_ACCESS = 0x0002;

            const int FILE_MAP_WRITE = 0x0002;

            [DllImport("Kernel32.dll", EntryPoint = "MapViewOfFile")]

            private static extern IntPtr MapViewOfFile(

             IntPtr hFileMappingObject,//HANDLE hFileMappingObject,

             UInt32 dwDesiredAccess,//DWORD dwDesiredAccess

             UInt32 dwFileOffsetHight,//DWORD dwFileOffsetHigh,

             UInt32 dwFileOffsetLow,//DWORD dwFileOffsetLow,

             UInt32 dwNumberOfBytesToMap//SIZE_T dwNumberOfBytesToMap

             );

            [DllImport("Kernel32.dll", EntryPoint = "UnmapViewOfFile")]

            private static extern int UnmapViewOfFile(IntPtr lpBaseAddress);

            [DllImport("Kernel32.dll", EntryPoint = "CloseHandle")]

            private static extern int CloseHandle(IntPtr hObject);

            private Semaphore m_Write;  //可写的信号

            private Semaphore m_Read;  //可读的信号

            private IntPtr handle;     //文件句柄

            private IntPtr addr;       //共享内存地址

            uint mapLength;            //共享内存长

            Thread threadRed;

            public AppTwoMain()

            {

                InitializeComponent();

                //threadRed = new Thread(new ThreadStart(init));

                //threadRed.Start();

                mapLength = 1024;

            }

            private void button1_Click(object sender, EventArgs e)

            {

                try

                {

                    m_Write = Semaphore.OpenExisting("WriteMap");

                    m_Read = Semaphore.OpenExisting("ReadMap");

                    handle = OpenFileMapping(FILE_MAP_WRITE, 0, "shareMemory");

                    addr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);

                    m_Write.WaitOne();

                    byte[] sendStr = Encoding.Default.GetBytes(textBox1.Text.ToString() + '');

                    //如果要是超长的话,应另外处理,最好是分配足够的内存

                    if (sendStr.Length < mapLength)

                        Copy(sendStr, addr);

                   

                    m_Read.Release();

                }

                catch (WaitHandleCannotBeOpenedException)

                {

                    MessageBox.Show("不存在系统信号量!");

                    return;

                }

            }

            static unsafe void Copy(byte[] byteSrc, IntPtr dst)

            {

                fixed (byte* pSrc = byteSrc)

                {

                    byte* pDst = (byte*)dst;

                    byte* psrc = pSrc;

                    for (int i = 0; i < byteSrc.Length; i++)

                    {

                        *pDst = *psrc;

                        pDst++;

                        psrc++;

                    }

                }

            }

        }

    }

  • 相关阅读:
    设计模式-行为型模式,python备忘录模式
    设计模式-行为型模式,python 中介者模式
    python 迭代器模式
    python对象池模式
    设计模式-结构型模式,python组合模式
    设计模式-结构型模式,python桥接模式
    python concurrent.futures.Threadpoolexcutor的有界队列和无界队列
    python加快数据处理的方法
    面向切面编程AOP,一些通用装饰器
    supervisor的command执行两条命令
  • 原文地址:https://www.cnblogs.com/lgx5/p/6697438.html
Copyright © 2011-2022 走看看