• 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);
            }
    
        }
    }
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Runtime.Remoting;
     5 using System.Runtime.Remoting.Channels;
     6 using System.Runtime.Remoting.Channels.Ipc;
     7 using System.Text;
     8 using System.Threading.Tasks;
     9 
    10 namespace IPCServer
    11 {
    12     class Program
    13     {
    14         static void Main(string[] args)
    15         {
    16             IpcServerChannel channel = new IpcServerChannel("ServerChannel");
    17             ChannelServices.RegisterChannel(channel, false);
    18             DataObj.LoadData();
    19             DataObj.salary.Add("jian", 23);
    20             DataObj.salary.Add("xun", 22);
    21             RemotingConfiguration.RegisterWellKnownServiceType(typeof(DataObj), "DataObj", WellKnownObjectMode.SingleCall);
    22 
    23             Console.WriteLine("press anykey to exit");
    24             Console.ReadKey();
    25         }
    26     }
    27 }
     1 using IPCServer;
     2 using System;
     3 using System.Collections.Generic;
     4 using System.Linq;
     5 using System.Runtime.Remoting.Channels;
     6 using System.Runtime.Remoting.Channels.Ipc;
     7 using System.Text;
     8 using System.Threading.Tasks;
     9 
    10 namespace IPCClient
    11 {
    12     class Program
    13     {
    14         static void Main(string[] args)
    15         {
    16             IpcClientChannel channel = new IpcClientChannel();
    17             ChannelServices.RegisterChannel(channel, false);
    18 
    19             DataObj obj = null;
    20 
    21             for (int t = 0; t < 1; t++)
    22             {
    23                 Console.WriteLine("t={0}", t);
    24                 try
    25                 {
    26                     obj = (DataObj)Activator.GetObject(typeof(DataObj), "ipc://ServerChannel/DataObj"); 
    27                 }
    28                 catch (Exception e)
    29                 {
    30                     Console.WriteLine(e.Message);
    31                 }
    32 
    33                 if (obj == null)
    34                 {
    35                     Console.WriteLine("could not locate server");
    36                 }
    37                 else
    38                 {
    39                     foreach (var pair in  obj.GetSalary())
    40                     {
    41                         Console.WriteLine("{0},{1}", pair.Key, pair.Value); 
    42                     }
    43                     Console.WriteLine("counter = {0}", obj.GetSalary());
    44                     DataObj.counter++;
    45                 }
    46             }
    47 
    48             Console.WriteLine("Mission Complete!");
    49             Console.ReadKey();
    50         }
    51     }
    52 }

    事实上结果并没有加速。估计IPC也是把对象序列化后传递,再反序列化的吧。 桑心。

    next steps: 寻找一种直接读其他进程的内存空间的途径。。。

  • 相关阅读:
    Windows批处理方式实现MySQL定期自动备份多个数据库
    MySQL数据库中库、表名、字段的大小写问题
    使用modbus4j通过串口解析modbus协议(java)
    mybatis —— 动态sql之if条件判断各种使用方式
    Mysql 获取表的comment 字段
    [转载]如何判断数据库,表或字段是否存在
    设计模式目录
    图片上传及访问
    实现第一个API
    ListView 源码解析
  • 原文地址:https://www.cnblogs.com/sylvanas2012/p/4294393.html
Copyright © 2020-2023  润新知