System.IO.Stream
送信する前にリスト全体をバッファリングせずに、オブジェクトのオープンエンドリストをにストリーミングし、もう一方の端からそれらを読み取る方法を探して、この質問にたどり着きました。(具体的には、永続化されたオブジェクトをMongoDBからWeb API経由でストリーミングしています。)
@Paul Tyngと@Riversは元の質問に答えるのに素晴らしい仕事をしました、そして私は彼らの答えを使って私の問題の概念実証を構築しました。他の誰かが同じ問題に直面している場合に備えて、ここにテストコンソールアプリを投稿することにしました。
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace TestJsonStream {
class Program {
static void Main(string[] args) {
using(var writeStream = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.None)) {
string pipeHandle = writeStream.GetClientHandleAsString();
var writeTask = Task.Run(() => {
using(var sw = new StreamWriter(writeStream))
using(var writer = new JsonTextWriter(sw)) {
var ser = new JsonSerializer();
writer.WriteStartArray();
for(int i = 0; i < 25; i++) {
ser.Serialize(writer, new DataItem { Item = i });
writer.Flush();
Thread.Sleep(500);
}
writer.WriteEnd();
writer.Flush();
}
});
var readTask = Task.Run(() => {
var sw = new Stopwatch();
sw.Start();
using(var readStream = new AnonymousPipeClientStream(pipeHandle))
using(var sr = new StreamReader(readStream))
using(var reader = new JsonTextReader(sr)) {
var ser = new JsonSerializer();
if(!reader.Read() || reader.TokenType != JsonToken.StartArray) {
throw new Exception("Expected start of array");
}
while(reader.Read()) {
if(reader.TokenType == JsonToken.EndArray) break;
var item = ser.Deserialize<DataItem>(reader);
Console.WriteLine("[{0}] Received item: {1}", sw.Elapsed, item);
}
}
});
Task.WaitAll(writeTask, readTask);
writeStream.DisposeLocalCopyOfClientHandle();
}
}
class DataItem {
public int Item { get; set; }
public override string ToString() {
return string.Format("{{ Item = {0} }}", Item);
}
}
}
}
が破棄されると例外が発生する可能性があることに注意してくださいAnonymousPipeServerStream
。当面の問題とは関係がないため、これは無視しました。