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

解决方案 »

  1.   

    memory file mapping内存映射文件, windows 上性能最好的 ipc 进程通信
      

  2.   

    进程之间的通讯,最好用socket,比较标准,
      

  3.   

    用socket,弄个服务器,在服务器存储数据,所有进程从服务器取,也更新服务器。
    其实更简单的方法,是webservice,wcf或remoting
      

  4.   

    同进程 ,多线程。 一个全局变量就可以多进程。可以用 webservice 等来实现。
      

  5.   

    多进程间通讯使用共享内存算是一种比较好的解决方案, QQ游戏大厅, 与QQ游戏之间通讯就是采用的这种方式 .
    C#实现可以参考 :
    http://blog.csdn.net/yefanqiu/article/details/1717458
      

  6.   

    是CS结构的应用程序,WEBService用不了。
    还有就是这三个线程同属于一个应用程序
      

  7.   

    进程共享:
    可以使用进程继承,DuplicateHandle进程句柄复制,还有个命名对象。。按照LZ的需求,后两者最合适
      

  8.   

    到底是多线程访问同一服务还是多进程?
    多线程的话直接可以用Invoke或者delegate等多进程的话涉及到windows的消息机制
    下面是一段接收端简单示例,基本上就是这样        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;
                }
            }
      

  9.   

    进程继承估计在C#实现不了,封装了除非自己写个VC的dll
    后者可以PInvoke该DuplicateHandle函数,至于函数详细可以参阅MSDN
    命名对象比如Semphore,Mutex,Monitor...都可以
      

  10.   

    问题一:开辟内存空间何解?你不是已经有了一个服务进程么?这个服务进程对访问它的其他客户端进程而言,不就是一段可以共享的内存空间么?
    问题二:进程间通讯我比较习惯用的是windows Message。至于数据最新,这个你自己设计相关逻辑去更新你服务进程中的数据。给你一个winMsg例子做参考Server发送数据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;
            }
    Client接收数据const int WM_COPYDATA = 0x004A;
            #region 消息机制数据载体
            //数据载体
            public struct COPYDATASTRUCT
            {
                public IntPtr dwData;
                public int cbData;
                [MarshalAs(UnmanagedType.LPStr)]
                public string lpData;
            }
            #endregion        #region 消息机制
            //窗体接收windows消息的方法
            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;
                }
            }
            #endregion
      

  11.   

    C#开辟内存空间是安全的吗?能否利用VC的机制生成dll,然后进行引用处理?
    C#操作类似于C++中的句柄(非windowsForm句柄)如何实现?
      

  12.   

    下面例子可以直接运行(需要VS2010,因为MemoryMappedFile是.net4才有)。
    编译通过后,先运行多个例子,看看互相之间的交互结果。其中MemoryMappedFile为共享内存,Mutex用来进行同步,ManualResetEvent用来通知有新的更新。
    更新通知很初级但基本有效,我有时间再作进一步解释。class Program
    {
        static void Main()
        {
            new Program().Run();
        }    void Run()
        {
            ThreadPool.QueueUserWorkItem(this.Observer);        string line;
            while ((line = Console.ReadLine()) != "")
            {
                Console.CursorTop = Console.CursorLeft = 0; 
                Console.Write(new string(' ', 80));
                Console.CursorTop = Console.CursorLeft = 0;             PutString(line);
            }
        }    List<string> lines = new List<string>();
        void DisplayLines()
        {
            Console.CursorTop = Console.CursorLeft = 0;
            Console.WriteLine(Environment.NewLine); 
            Console.ForegroundColor = ConsoleColor.DarkGreen;
            foreach (string line in lines)
            {
                Console.WriteLine(line);
            }
            Console.ForegroundColor = ConsoleColor.Gray;
            Console.CursorTop = Console.CursorLeft = 0;
        }    void Observer(object state)
        {
            int lastOffset = sizeof(int);
            while (true)
            {
                notifyEvent.WaitOne();
                if (GetStrings(ref lastOffset) == false)
                {
                    Thread.Sleep(50);
                }
            }
        }    void PutString(object state)
        {
            byte[] bytes = System.Text.Encoding.UTF8.GetBytes(state as string);
            try
            {
                mutex.WaitOne();
                using (MemoryMappedViewAccessor accessor = memMap.CreateViewAccessor())
                {
                    int offset = accessor.ReadInt32(0); offset = Math.Max(sizeof(int), offset);
                    accessor.Write(offset, (int)bytes.Length); offset += sizeof(int);
                    accessor.WriteArray<byte>(offset, bytes, 0, bytes.Length); offset += bytes.Length;
                    accessor.Write(0, offset);
                }
            }
            finally
            {
                mutex.ReleaseMutex();
            }
            notifyEvent.Set();
            Thread.Sleep(100);
            notifyEvent.Reset();
        }    bool GetStrings(ref int lastOffset)
        {
            try
            {
                mutex.WaitOne();
                using (MemoryMappedViewAccessor accessor = memMap.CreateViewAccessor())
                {
                    int newOffset = accessor.ReadInt32(0);
                    if (newOffset <= lastOffset) return false;                for (int offset = lastOffset; offset < newOffset; )
                    {
                        int stringLength = accessor.ReadInt32(offset); offset += sizeof(int);                    byte[] bytes = new byte[stringLength];
                        accessor.ReadArray<byte>(offset, bytes, 0, bytes.Length); offset += stringLength;                    this.lines.Add(Encoding.UTF8.GetString(bytes));
                    }
                    lastOffset = newOffset;
                }
            }
            finally
            {
                mutex.ReleaseMutex();
            }
            DisplayLines();
            return true;
        }    Mutex mutex = new Mutex(false, "MyMutex");
        MemoryMappedFile memMap = MemoryMappedFile.CreateOrOpen("MyMemoryMap", 64 * 1024);
        EventWaitHandle notifyEvent = new EventWaitHandle(false, EventResetMode.ManualReset, "MyNotifyEvent");
    }