在c#中,可能大多数人针对于多线程之间的通讯,是熟能生巧,对于AsyncLocal 和ThreadLocal以及各个静态类中支持线程之间传递的GetData和SetData方法都是信手拈来,那多进程通讯呢,实际上也是用的比较多的地方,但是能够熟能生巧的人和多线程的相比的话呢,那还是有些差距的,所以我昨天整理了一下我所认知的几个多进程之间的通讯方式,这其中是不包括各种消息中间件以及数据库方面的,还有Grpc,WebSocket或者Signalr等方式,仅仅是以c#代码为例,c#的多进程通讯呢,大致上是分为这几类的,共享内存,借助Windows的MSMQ消息队列服务,以及命名管道和匿名管道,以及IPC HTTP TCP的Channel的方式,还有常用的Socket,借助Win32的SendMessage的Api来实现多进程通讯,还有最后一种就是多进程之间的信号量相关的Mutex,代码我会放在文章的末尾,大家有需要的话可以去下载来看看,接下来就为大家一一奉上。
共享内存共享内存呢,实际上c#中可以有很多种实现方式,主要是借助于Win32的Api来实现以及,使用MemoryMappedFile这个类来实现共享内存,前者需要引入多个Win32的dll的方法,后者使用起来就比较简单,只需要调用类的CreatNew方法设置好内存映射文件名称以及大小,以及操作权限就可以实现,同时支持Accessor和Stream的方式去进行读写,但是性能方面肯定是Win32的性能好,而且Win32的话不受语言的限制,至于这个类是否受限于语言,目前我是不太清楚的。接下来,咱们就看看客户端和服务端使用共享内存的方式和获取数据的代码。
服务端:
MemoryMappedFile memoryAccessor = MemoryMappedFile.CreateNew("ProcessCommunicationAccessor", 500, MemoryMappedFileAccess.ReadWrite);//创建共享内存映射文件对象,第一个参数为映射的名称,与客户端需要对应,500为大小,单位为字节,MemoryMappedFileAccess为访问权限,是读写还是只读 只写,此处不能使用Using 否则脱离Using 就会释放,客户端无法获取到此名称的内存映射对象 using (var accessor = memoryAccessor.CreateViewAccessor())//获取映射文件对象的视图 { var helo = Encoding.UTF8.GetBytes("Accessor"); accessor.WriteArray(0, helo, 0, helo.Length);//将给定的值写入此视图中 richTextBox1.Text += Environment.NewLine + "Accessor Send Val:Accessor"; } MemoryMappedFile memoryStream = MemoryMappedFile.CreateNew("ProcessCommunicationStream", 500, MemoryMappedFileAccess.ReadWrite);//创建流的映射文件对象 using (var stream = memoryStream.CreateViewStream())//获取映射文件的流 { var helo = Encoding.UTF8.GetBytes("Stream"); stream.Write(helo, 0, helo.Length);//将给定的值写入此内存流中 richTextBox1.Text += Environment.NewLine + "Accessor Send Val:Stream"; }