日期:2014-05-18  浏览次数:20986 次

如何实现开辟一块共享内存和多线程访问该内存?
有一个服务进程S,它包含大量的数据,系统中还有另外几个进程,定义为:进程a,进程b,进程c
现在进程a、b、c都要对服务进程S进行访问,且进行数据的读写交互,且保证每个进程当前读S进程的数据是最新的。
我个人认为进程S需要开辟一块内存区域,且进程a,b,c都要对该内存进行访问和数据的通信。
但是C#如何开辟内存呢?进程之间是怎么通信的呢?有如何保证每个进程得到的服务进程的数据都是最新的呢?
网上也查了一些资料,搞得一头雾水,请牛人们给些指点,谢谢!

------解决方案--------------------
memory file mapping

内存映射文件, windows 上性能最好的 ipc 进程通信
------解决方案--------------------
你要在多进程共享内存,还是多线程共享内容,

多线程共享内存很容易实现,每个线程访问的内存空间其实都是共享的,所以所有的静态变量都可以作为多个线程共享的内存空间,

进程就麻烦了,只能用内存映射文件,
------解决方案--------------------
进程之间的通讯,最好用socket,比较标准,
------解决方案--------------------
用socket,弄个服务器,在服务器存储数据,所有进程从服务器取,也更新服务器。
其实更简单的方法,是webservice,wcf或remoting
------解决方案--------------------
同进程 ,多线程。 一个全局变量就可以

多进程。可以用 webservice 等来实现。
------解决方案--------------------
多进程间通讯使用共享内存算是一种比较好的解决方案, QQ游戏大厅, 与QQ游戏之间通讯就是采用的这种方式 .
C#实现可以参考 :
http://blog.csdn.net/yefanqiu/article/details/1717458
------解决方案--------------------
进程共享:
可以使用进程继承,DuplicateHandle进程句柄复制,还有个命名对象。。

按照LZ的需求,后两者最合适
------解决方案--------------------
到底是多线程访问同一服务还是多进程?
多线程的话直接可以用Invoke或者delegate等

多进程的话涉及到windows的消息机制
下面是一段接收端简单示例,基本上就是这样
C# code

        protected override void DefWndProc(ref System.Windows.Forms.Message m)
        {
            switch (m.Msg)
            {
                case WM_COPYDATA:
                    //your process
                    break;
                default:
                    base.DefWndProc(ref m);
                    break;
            }
        }

------解决方案--------------------
问题一:开辟内存空间何解?你不是已经有了一个服务进程么?这个服务进程对访问它的其他客户端进程而言,不就是一段可以共享的内存空间么?
问题二:进程间通讯我比较习惯用的是windows Message。至于数据最新,这个你自己设计相关逻辑去更新你服务进程中的数据。

给你一个winMsg例子做参考

Server发送数据
C# code

private static void YourSendMessage(string strSendingData)
        {
            //调用发送消息方法
            sendMessage(strSendingData);
        }

        const int WM_COPYDATA = 0x004A;

        //发送消息
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessage(
            int hWnd,
            int Msg,
            int wParam,
            ref COPYDATASTRUCT lParam
        );


        //通过窗口标题找到窗口
        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        private static extern int FindWindow(string lpClassName, string lpWindowName);
        public static void sendMessage(string strSendingMsg)
        {
            string winName = "";    //你想要发送的窗口标题
            int window_handler = FindWindow(null, @winName);
            if (window_handler != 0)
            {
                byte[] byt = System.Text.Encoding.Default.GetBytes(strSendingMsg);
                int len = byt.Length;
                COPYDATASTRUCT cds;
                cds.dwData = (IntPtr)100;
                cds.lpdata = strSendingMsg;
                cds.cbData = len + 1;

                SendMessage(window_handler, WM_COPYDATA, 0, ref cds);
            }
        }

        public struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpdata;
        }

------解决方案--------------------
下面例子可以直接运行(需要VS2010,因为MemoryMappedFile是.net4才有)。
编译通过后,先运行