用管道实现流的分支
1. 简介
前一篇文章提到了如何将输出流转换为输入流,用同样的方法可以实现流的分支,就是将一个输出流的内容同时发送给两或多个输入流。
2. 应用场景
当需要将数据处理过程中一个中间结果以流的形式传递个两个或者多个处理程序时候,就需要对流进行分支,如果中间结果是以输入流的形式出现,那处理方法就很直观很简单了,但是多数情况下,中间结果是以输出流的形式出现的,这个时候还是输出流转输入流的问题,只是更进一步,可以将一个输出流转换为两个或多个输入流,这样就实现了流的分支。
3. 实现代码
1 [TestMethod] 2 public void OutputStream2MultiInputStreamUsingPipe() 3 { 4 const int iStreamSize = 128 * 1024; 5 6 var md51 = ""; 7 var md52 = ""; 8 9 10 var t1 = new Thread((data) => 11 { 12 using (var pipe = new AnonymousPipeClientStream( 13 PipeDirection.In, (string)data)) 14 { 15 md51 = Utils.GetStreamMD5AsHexString(pipe); 16 } 17 }); 18 19 var t2 = new Thread((data) => 20 { 21 using (var pipe = new AnonymousPipeClientStream( 22 PipeDirection.In, (string)data)) 23 { 24 md52 = Utils.GetStreamMD5AsHexString(pipe); 25 } 26 }); 27 28 using (var ms = new MemoryStream()) 29 { 30 using (var pipe1 = new AnonymousPipeServerStream( 31 PipeDirection.Out, HandleInheritability.Inheritable)) 32 { 33 t1.Start(pipe1.GetClientHandleAsString()); 34 35 using (var pipe2 = new AnonymousPipeServerStream( 36 PipeDirection.Out, HandleInheritability.Inheritable)) 37 { 38 t2.Start(pipe2.GetClientHandleAsString()); 39 40 for (var i = 0; i < iStreamSize; i++) 41 ms.WriteByte((byte) 'A'); 42 ms.Position = 0; 43 Utils.CopyStream(ms, pipe1, pipe2); 44 } 45 46 } 47 t1.Join(); 48 t2.Join(); 49 Console.WriteLine(md51); 50 Assert.AreEqual(md51, md52); 51 52 } 53 }
同样的方法可以实现3个或更多个分支。
4. 应用限制
Pipe的一个限制就是它不支持Seek,因为它是用一小块缓存来进行数据交换。因此这个方法只适用于顺序写入和顺序读取的流。