大学IT网 - 最懂大学生的IT学习网站! QQ资料交流群:367606806
当前位置:大学IT网 > C#技巧 > 进程间通信的一个方法

进程间通信的一个方法(1)

关键词:进程间通信  阅读(1421) 赞(50)

[摘要]本文介绍了进程间通信的一个方法,一起学习。

网上关于C#进程间通信的资料:WM_COPYDATA、共享内存、管道、消息队列、SOCKET...其中WM_COPYDATA是最简单的,但它受制于窗口。当窗口不处在顶层时,WM_COPYDATA就可能失效。共享内存是较为基础的一种办法,但要用好它需要一些技巧。另外小弟对进程间消息传递的及时性非常看重,希望一个进程发出消息后,目标进程能够立即做出反应。但是进程边界决定了这是不可能的,因为发送消息的进程不可能直接调用目标进程里的函数。归根结底,目标进程得自己通过循环来查看外面是否有属于自己的消息。WM_COPYDATA是通过窗口消息循环来获取,其它几种方法则是在内部通过一个while循环来获取信息。因为要避免这个while循环影响到UI线程,所以必需另开线程。在了解了进程间通迅一些基础原理后,小弟总结出自己的方法。其原理是:

以共享内存为基础,发送方将消息码(代表了消息含义)及消息相关数据,以及接收进程的标识(进程ID或主窗口Text)都放到共享内存中。接收方则循环检查共享内存中有无属于自己的消息数据,若有则取出处理。处理完后接收方将共

享内存数据清空。


    public static class ProcessMessaging
    {
        static ShareMem Data = new ShareMem();

        /// <summary>
        /// 获取共享内存(MyData结构)
        /// </summary>
        /// <returns></returns>
        public static MyData GetShareMem()
        {
            int MemSize = Marshal.SizeOf(typeof(MyData));

            if (Data.Init("MyData", MemSize) != 0)
            {
                return new MyData(-1);
            }

            byte[] temp = new byte[MemSize];

            try
            {
                Data.Read(ref temp, 0, temp.Length);
                MyData stuc = (MyData)Tools.BytesToStuct(temp, typeof(MyData));
                return stuc;
            }
            catch (Exception)
            {
                return new MyData(-1);
            }
        }//end fun

        /// <summary>
        /// 设置共享内存(MyData结构)
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool SetShareMem(MyData data)
        {
            int MemSize = Marshal.SizeOf(typeof(MyData));

            if (Data.Init("MyData", MemSize) != 0)//"MyData"共享内存名称,您起别的名字也可以
            {
                return false;
            }

            try
            {
                byte[] b = Tools.StructToBytes(data);
                Data.Write(b, 0, b.Length);
            }
            catch (Exception)
            {
                return false;
            }
            return true;
        }//end fun
    }//end class

    public class ShareMem
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr CreateFileMapping(int hFile, IntPtr lpAttributes, uint flProtect, 

uint dwMaxSizeHi, uint dwMaxSizeLow, string lpName);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr OpenFileMapping(int dwDesiredAccess, [MarshalAs

(UnmanagedType.Bool)] bool bInheritHandle, string lpName);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr MapViewOfFile(IntPtr hFileMapping, uint dwDesiredAccess, uint 

dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern bool UnmapViewOfFile(IntPtr pvBaseAddress);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern bool CloseHandle(IntPtr handle);

        [DllImport("kernel32", EntryPoint = "GetLastError")]
        public static extern int GetLastError();

        const int ERROR_ALREADY_EXISTS = 183;

        const int FILE_MAP_COPY = 0x0001;
        const int FILE_MAP_WRITE = 0x0002;
        const int FILE_MAP_READ = 0x0004;
        const int FILE_MAP_ALL_ACCESS = 0x0002 | 0x0004;

        const int PAGE_READONLY = 0x02;
        const int PAGE_READWRITE = 0x04;
        const int PAGE_WRITECOPY = 0x08;
        const int PAGE_EXECUTE = 0x10;
        const int PAGE_EXECUTE_READ = 0x20;
        const int PAGE_EXECUTE_READWRITE = 0x40;

        const int SEC_COMMIT = 0x8000000;
        const int SEC_IMAGE = 0x1000000;
        const int SEC_NOCACHE = 0x10000000;
        const int SEC_RESERVE = 0x4000000;

        const int INVALID_HANDLE_VALUE = -1;

        IntPtr m_hSharedMemoryFile = IntPtr.Zero;
        IntPtr m_pwData = IntPtr.Zero;
        bool m_bAlreadyExist = false;
        bool m_bInit = false;
        long m_MemSize = 0;

        public ShareMem()
        {
        }

        ~ShareMem()
        {
            Close();
        }

        /// <summary>
        /// 初始化共享内存
        /// </summary>
        /// <param name="strName">共享内存名称</param>
        /// <param name="lngSize">共享内存大小</param>
        /// <returns></returns>
        public int Init(string strName, long lngSize)
        {
            if (lngSize <= 0 || lngSize > 0x00800000) lngSize = 0x00800000;
            m_MemSize = lngSize;
            if (strName.Length > 0)
            {
                //创建内存共享体(INVALID_HANDLE_VALUE)
                m_hSharedMemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, (uint)

PAGE_READWRITE, 0, (uint)lngSize, strName);
                if (m_hSharedMemoryFile == IntPtr.Zero)
                {
                    m_bAlreadyExist = false;
                    m_bInit = false;
                    return 2; //创建共享体失败
                }
                else
                {
                    if (GetLastError() == ERROR_ALREADY_EXISTS)  //已经创建
                    {
                        m_bAlreadyExist = true;
                    }
                    else                                         //新创建
                    {
                        m_bAlreadyExist = false;
                    }
                }
                //---------------------------------------
                //创建内存映射
                m_pwData = MapViewOfFile(m_hSharedMemoryFile, FILE_MAP_WRITE, 0, 0, (uint)lngSize);
                if (m_pwData == IntPtr.Zero)
                {
                    m_bInit = false;
                    CloseHandle(m_hSharedMemoryFile);
                    return 3; //创建内存映射失败
                }
                else
                {
                    m_bInit = true;
                    if (m_bAlreadyExist == false)
                    {
                        //初始化
                        MyData data = new MyData(-1);
                        byte[] bd = Tools.StructToBytes(data);
                        Marshal.Copy(m_pwData, bd, 0, bd.Length);
                    }
                }
                //----------------------------------------
            }
            else
            {
                return 1; //参数错误     
            }

            return 0;     //创建成功
        }//end fun

        /// <summary>
        /// 关闭共享内存
        /// </summary>
        public void Close()
        {
            if (m_bInit)
            {
                UnmapViewOfFile(m_pwData);
                CloseHandle(m_hSharedMemoryFile);
            }
        }

        /// <summary>
        /// 读数据
        /// </summary>
        /// <param name="bytData">数据</param>
        /// <param name="lngAddr">起始地址</param>
        /// <param name="lngSize">个数</param>
        /// <returns></returns>
        public int Read(ref byte[] bytData, int lngAddr, int lngSize)
        {
            if (lngAddr + lngSize > m_MemSize) return 2; //超出数据区
            if (m_bInit)
            {
                Marshal.Copy(m_pwData, bytData, lngAddr, lngSize);
            }
            else
            {
                return 1; //共享内存未初始化
            }
            return 0;     //读成功
        }

        /// <summary>
        /// 写数据
        /// </summary>
        /// <param name="bytData">数据</param>
        /// <param name="lngAddr">起始地址</param>
        /// <param name="lngSize">数据长度</param>
        /// <returns></returns>
        public int Write(byte[] bytData, int lngAddr, int lngSize)
        {
            if (lngAddr + lngSize > m_MemSize) return 2; //超出数据区
            if (m_bInit)
            {
                Marshal.Copy(bytData, lngAddr, m_pwData, lngSize);
            }
            else
            {
                return 1; //共享内存未初始化
            }
            return 0;     //写成功
        }
    }//end class


«上一页12下一页»


相关评论