我可以使用以下代码读取2个线程通过NamedPipeClientStreams发送的消息:
客户端:
private static async void DoLogging(string context)
{
try
{
var pipeClient = new NamedPipeClientStream(".", PipeName, PipeDirection.InOut, PipeOptions.Asynchronous);
for (var i = 0; i < 10; i++)
{
if (!pipeClient.IsConnected)
pipeClient.Connect(1000);
var buffer = Encoding.UTF8.GetBytes($"Context {context}: Message {i}");
await pipeClient.WriteAsync(buffer, 0, buffer.Length);
pipeClient.Flush();
Thread.Sleep(100); // For testing purposes
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
服务器:
private static void ListenForConnection()
{
while (true)
{
var pipeServer = new NamedPipeServerStream(PipeName, PipeDirection.InOut,
NamedPipeServerStream.MaxAllowedServerInstances,
PipeTransmissionMode.Message, PipeOptions.Asynchronous);
var namedPipeListener = pipeServer.WaitForConnectionAsync(CancellationToken.None).ToObservable();
namedPipeListener.SubscribeOn(Scheduler.Default).Subscribe(unit =>
{
HandleClient(pipeServer);
});
}
}
private static void HandleClient(PipeStream pipeServer)
{
var bytes = new byte[BufferSize];
var sb = new StringBuilder();
while (true)
{
int numBytes;
do
{
numBytes = pipeServer.Read(bytes, 0, BufferSize);
if (numBytes > 0)
{
sb.Append(Encoding.UTF8.GetString(bytes, 0, numBytes));
}
} while (numBytes > 0 && !pipeServer.IsMessageComplete);
var text = sb.ToString();
if (!string.IsNullOrWhiteSpace(text))
{
Console.WriteLine(text.Trim());
sb.Clear();
}
}
}
以上称为:
private const string PipeName = "SvTest.Pipe.Name";
private const int BufferSize = 1024;
private static void Main()
{
try
{
var tasks = new Task[3];
tasks[0] = Task.Run(() => ListenForConnection());
tasks[1] = Task.Run(() => DoLogging("Thread 1"));
tasks[2] = Task.Run(() => DoLogging("Thread 2"));
Task.WaitAll(tasks);
}
catch (Exception ex)
{
LogException(ex);
}
Console.ReadLine();
}
如果我尝试使用RX读取流,我可以读取第一条消息,然后我得到一个&#34;管道坏了&#34; HandleClient方法如下所示的客户端线程中的错误:
private static void HandleClient(Stream pipeStream)
{
var buffer = new byte[pipeStream.Length];
var sb = new StringBuilder();
var readObservable = pipeStream.ReadAsync(buffer, 0, buffer.Length).ToObservable();
readObservable.SubscribeOn(Scheduler.Default).Subscribe(
unit =>
{
Read(buffer, sb);
},
OnError,
() => { ReadCompleted(sb); }, CancellationToken.None);
}
我假设服务器流在读取后关闭。我不确定如何保持流打开并从中读取。我能够找到的代码示例和文档使用旧的APM技术。我想使用.Net 4.6和RX库提供的最新/推荐技术。在我的应用程序中,客户端将在很长一段时间内随意发送消息。所以我希望管道保持每个客户端打开,以免每条消息产生连接开销。
我也很感谢关于边缘情况的任何指导,以便我最终得到坚如磐石的解决方案。