はい.NETでパイプを使用して出力ストリームを入力ストリームに変換

3809 ワード

最近、コードを書き、ローカルファイルを圧縮暗号化してサーバに送信し、サーバに送信したクラスは入力ストリームをパラメータとしてアップロードするデータを取得し、圧縮クラスと暗号化クラスは出力ストリームである.
出力ストリームを入力ストリームに変換する方法は、最も直感的な方法は、出力ストリームのすべての内容をメモリまたはファイルにキャッシュすることですが、データが大きくなると、この2つの方法は明らかに適切ではありません.
パイプを使用すると、出力ストリームを入力ストリームに変換できます.パイプは1つのオペレーティングシステムの機能で、1つの循環キャッシュ領域から構成され、プロセス間の通信に用いられ、1つのプロセスの出力を別のプロセスの入力とし、Linuxコマンドラインスクリプトはパイプ通信に大量に用いられ、Windowsも同様にパイプをサポートする.Netはパイプにカプセル化されたクラスがあり、パイプを使用して2つのスレッド間で通信し、1つのプロセスの出力を別のプロセスに入力として伝達する.NetではパイプクラスがStreamクラスから継承され,出力ストリームを入力ストリームにシームレスに接続できる.
AnonymousPipeClientStreamクラスとAnonymousPipeServerStreamクラスのドキュメントを参照して、プロセス間通信をスレッド間通信に変更すると、1つのアプリケーションで出力クラスを入力クラスに変換する機能が実現されます.コードは次のとおりです.
 1         [TestMethod]
 2         public void OutputStream2InputStreamUsingPipe()
 3         {
 4             int iStreamSize = 128 * 1024;
 5 
 6             var t = new Thread((data) =>
 7                 {
 8                     using (var pipe = new AnonymousPipeClientStream(
 9                         PipeDirection.Out, (string)data))
10                     {
11                         for (var i = 0; i < iStreamSize; i++)
12                             pipe.WriteByte((byte)'A');
13                     }
14                 });
15 
16             using (var ms = new MemoryStream())
17             {
18                 using (var pipe = new AnonymousPipeServerStream(
19                     PipeDirection.In, HandleInheritability.Inheritable))
20                 {
21                     t.Start(pipe.GetClientHandleAsString());
22                     var buffer = new byte[8 * 1024];
23                     int len;
24                     while ((len = pipe.Read(buffer, 0, buffer.Length)) > 0)
25                     {
26                         Thread.Sleep(100);
27                         ms.Write(buffer, 0, len);
28                     }
29                 }
30                 t.Join();
31                 Assert.AreEqual(iStreamSize, ms.Length);
32             }
33         }

上記のコードでは、新しいスレッドでパイプの一端にデータを書き込み、メインスレッドでパイプの他端からデータを読み出す.書き込み前と読み出し後の両方でデータを処理する必要がある場合、2つのスレッドにデータ処理作業を割り当てることができれば、ストリーム変換の問題を解決することができ、また、データ処理作業にCPUを多く消費すると、2つのスレッドによる効率向上は、パイプによるオーバーヘッドを相殺するだけでなく、全体の効率をさらに向上させ、一挙両得である.
コード中Sleep(100)は、パイプの書き込みと読み出しを明確に同期させず、パイプの機能を検証する:読み取りスレッドがSleep状態に入ると、パイプバッファがいっぱいになり(windowsとlinuxの下のキャッシュ領域はいずれもメモリページ4 Kである可能性がある)、書き込み操作がブロックされる.