c# 进程间通信 IPC
最近在调试一个算法,想通过改变算法的参数看看结果有什么变化。 碰到一个麻烦的事情是,从磁盘加载、构建数据需要15分钟。这就比较讨厌了,也就是说我每次调一个参数前都要等15分钟启动时间?
于是我就想,能不能开一个datahost进程专门加载数据。我在别的进程调试参数,但需要用数据时就直接从datahost进程中加载现成的数据。 这样的话我只需要从磁盘加载一次数据。 于是找了一下, c#有个叫IPC(inter process communication)的功能可以实现同一台机器上的不同进程间通信。
注意我这里的scenario:我需要进程间通信“数据对象”, 而不是消息。 通信消息比较好办,就传一个string流就行了。而我需要传递的是数据对象,比如一个Dictionary, 或者自定义class。
IPC的大致过程是这样的:datahost进程先绑定一个对象,client根据对象的uri去访问对象类, 并且调用该类的方法。datahost进程接收到从client发来的调用,就会实例化一个对象(注意,在这个时候才开始实例化一个对象,这也是我的代码里使用static的原因),并且执行相关的函数,再把结果返回给client。 注意执行过程是在datahost端的。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace IPCServer { public class DataObj : MarshalByRefObject { public static Dictionary<string, int> salary; public static string company; public static int counter; public static int constructerCnt = 0; public static void LoadData() { company = "Microsoft"; salary = new Dictionary<string, int>(); salary.Add("lianjx", 3); salary.Add("uncle", 5); counter = 0; } public Dictionary<string, int> GetSalary() { return DataObj.salary; } public DataObj() { DataObj.constructerCnt++; Console.WriteLine("Constructer...{0}", DataObj.constructerCnt); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Ipc; using System.Text; using System.Threading.Tasks; namespace IPCServer { class Program { static void Main(string[] args) { IpcServerChannel channel = new IpcServerChannel("ServerChannel"); ChannelServices.RegisterChannel(channel, false); DataObj.LoadData(); DataObj.salary.Add("jian", 23); DataObj.salary.Add("xun", 22); RemotingConfiguration.RegisterWellKnownServiceType(typeof(DataObj), "DataObj", WellKnownObjectMode.SingleCall); Console.WriteLine("press anykey to exit"); Console.ReadKey(); } } }
using IPCServer; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Ipc; using System.Text; using System.Threading.Tasks; namespace IPCClient { class Program { static void Main(string[] args) { IpcClientChannel channel = new IpcClientChannel(); ChannelServices.RegisterChannel(channel, false); DataObj obj = null; for (int t = 0; t < 1; t++) { Console.WriteLine("t={0}", t); try { obj = (DataObj)Activator.GetObject(typeof(DataObj), "ipc://ServerChannel/DataObj"); } catch (Exception e) { Console.WriteLine(e.Message); } if (obj == null) { Console.WriteLine("could not locate server"); } else { foreach (var pair in obj.GetSalary()) { Console.WriteLine("{0},{1}", pair.Key, pair.Value); } Console.WriteLine("counter = {0}", obj.GetSalary()); DataObj.counter++; } } Console.WriteLine("Mission Complete!"); Console.ReadKey(); } } }
事实上结果并没有加速。估计IPC也是把对象序列化后传递,再反序列化的吧。 桑心。
next steps: 寻找一种直接读其他进程的内存空间的途径。。。
转至:http://www.cnblogs.com/sylvanas2012/p/4294393.html