私たちは流れ、APIのtreamで始まり、相対的に言って、我々は非常に精通しています。
問題はそれのいくつかのストリーミングとは何ですか?ブラー:さまざまなシーンでの異なるモードを使用します:
-
時には、読み取り専用、書き込み専用で、時には、時にはそれが同時に読み取りおよび書き込みです。
-
読み取り専用存在し得るにも同じ状況下で、書き込み専用(例:DeflateStream)しばらく
-
いくつかのデュアルストリーム(NetworkStream、SslStream)の状況では、ほとんど不可能データ送信を終了する際に知っている、とだけループ処理を継続して使用することができます。
-
異なるストリームの位置決め動作、いくつかの長さ、ある位置
-
大量のデータ、メモリ割り当てをコピーします。このような観点から、パイプラインは、.NETコア2.1に加えました。
どのようなパイプラインパイプラインは、メモリ管理(メモリの統合、回復)を含むバイナリストリームのAPIへのアクセスのセット、フロー制御(バックログと流出防止)、マルチスレッドの管理を提供するために理解することができます。
-
ストリーム
使用(MemoryStreamをミリ秒=新規のMemoryStream()) { WriteSomeData(MS)。 ms.Position = 0; ReadSomeData(MS)。 } ボイドWriteSomeData(ストリームstream) { バイト[]バイト=のEncoding.ASCII.GetBytes( "こんにちは、世界!")。 stream.Write(バイト0、bytes.Length)。 stream.Flush(); } ボイドReadSomeData(ストリームstream) { int型bytesRead。 バイト[]バッファ=新しいバイト[256]。 実行 { bytesRead = stream.Read(バッファ、0、buffer.Length)。 (bytesRead> 0)であれば { 文字列s = Encoding.ASCII.GetString(バッファ、0、bytesRead)。 Console.Write(S); } }一方(bytesRead> 0)。 }
-
パイプライン
非同期タスクProcessPipe() { パイプパイプ=新しいパイプ()。 WriteSomeDataAsync(pipe.Writer)待ちます。 pipe.Writer.Complete(); ReadSomeDataAsync(pipe.Reader)待ちます。 } ValueTask WriteSomeDataAsync(PipeWriterライタ)非同期 { メモリ<バイト>ワークスペース= writer.GetMemory(512)。 バイト= Encoding.ASCII.GetBytes(int型 "!こんにちは、世界"、workspace.Span)。 writer.Advance(バイト)。 )(writer.FlushAsyncを待ちます。 } ValueTask ReadSomeDataAsync(PipeReaderリーダ)非同期 { (真)一方 { ReadResult)は=は(reader.ReadAsyncを待つ読み取ります。 ReadOnlySequence <バイト>バッファ= read.Buffer。 (buffer.IsEmpty && read.IsCompleted)であれば ブレーク。 (buffer.IsSingleSegment)であれば { Encoding.ASCII.GetString(buffer.First)。 }他 { foreachの(メモリバッファ内の<バイト>セグメント) { 文字列s = Encoding.ASCII.GetString(segment.Span)。 Console.Write(S); } } reader.AdvanceTo(buffer.End)。 } }
二つの別々のパイプラインを提供読み、APIの問題を読み、書きます。
pipewriter:
GetMemoryを使用して、書き込み動作、パイプラインを処理するバイト[]を割り当て代替ディスプレイメモリを得ます。その後、パイプに書き込みます。これは、あなたが単一のデータがアドバンス(バイト)によって書かれ、バイトが1万バイトでもゼロにすることができ、512バイトを使用して終了し、同時にパイプラインがリーダーを消費することができますどのくらいのデータ通知ではありません。フラッシュパイプの後。
データの書き込みが完了した後、パイプへの書き込みの終了を通知するために、完全なメソッドを呼び出します。
pipereader:
read.IsCompleted
それは完全かどうかライターを表します。
buffer.IsEmpty
パイプラインの前の反復の単一の種にデータがないかどうかを教えてください。
AdvanceTo
私たちは、どのくらいのパイプラインデータ、消費者に伝える必要があります。
他の
列子の上に我々はAdvanceTo(buffer.End)を使用し、すべてを消費します。より一般的な場合は、自己定義されたデータ形式であるかによってもよいcr/lf
ので、カットオフデータの処理、すなわち消費者の長さが512バイト未満521以上であってもよいです。ReadOnlySequence<byte>
-
Slice()
この方法は、私たちの真のスライスによって処理されるデータを返すことができます。 -
GetPosition()
位置は逆のプロセスを取得します。 -
reader.AdvanceTo(consumedToPosition, buffer.End)
私たちは、私たちが扱うことができないエンドポイントデータへの消費ポイントのすべてのデータを確認しながら、我々は処理するために多くのデータを必要とする、消費者どのくらいのパイプラインの位置を指示する必要があります。
戻って見てPipeWriter.FlushAsync()
とPipeReader.ReadAsync()。
それらの間の微妙なバランスがあります。
-
ReadAsync
配管に必要なデータが、それは、読者を目覚め読み出しサイクルを実行します。 -