当使用C#NamedPipeServerStream时,如果客户端没有发送任何消息结束模式(如服务器使用ReadLine()读取时为\ r \ n)NamedPipeServerStream Read方法将永远等待并且没有Abort()或Interupt( )方法将在该线程上工作。
自:
1)NamedPipeServerStream不支持Stream.ReadTimeout
2)Abort()或Interupt()在线程上不起作用
3)NamedPipeServerStream.Disconnect()下面的工作
目前还不清楚,如何在NamedPipeServerStream读取操作上设置超时?
让我举一个例子。 IPC的规范我们要求交换\ 0终止的字符串。客户端发送消息,服务器处理消息,并且“必须”发送响应。 如果客户端最终没有发送\ 0(客户端不是我们的,那么我们无法保证其正常工作),Read方法将永远等待,而客户端(因为我们不控制它)可能会永远等待也是一个回应。
接下来是一个简化的实现示例:
public void RestartServer()
{
_pipeServerThread.Interrupt(); //doesn't affect Read wait
_pipeServerThread.Abort(); //doesn't affect Read wait
}
private void PipeServerRun(object o) //runs on _pipeServerThread
{
_pipeServer = new NamedPipeServerStream(_pipeName, InOut, 100,
PipeTransmissionMode.Message, PipeOptions.WriteThrough);
//_pipeServer.ReadTimeout = 100; //System.InvalidOperationException: Timeouts are not supporte d on this stream.
// Wait for a client to connect
while (true)
{
_pipeServer.WaitForConnection();
string request = ReadPipeString();
//... process request, send response and disconnect
}
}
/// <summary>
/// Read a \0 terminated string from the pipe
/// </summary>
private string ReadPipeString()
{
StringBuilder builder = new StringBuilder();
var streamReader = new StreamReader(_pipeServer);
while (true)
{
//read next byte
char[] chars = new char[1];
streamReader.Read(chars, 0, 1); // <- This will wait forever if no \0 and no more data from client
if (chars[0] == '\0') return builder.ToString();
builder.Append(chars[0]);
}
}
那么如何在NamedPipeServerStream读取操作上设置超时?
答案 0 :(得分:2)
由于您在消息模式下运行管道,因此应首先将整个消息读入byte[]
缓冲区或内存流,然后决定它是否有效并对其进行解码。管道消息有一定的长度。它无法显式检索,但是当您从消息模式管道中读取时会显示它。如果消息中仍有未读字节,Win32 ReadFile
将失败并显示ERROR_MORE_DATA
,然后返回TRUE
以指示消息已结束。在此之后,对ReadFile
的调用将会阻止,直到有新消息可用。 StreamReader
自然不知道这一点并阻止你的线程。
更新以实现超时,使用异步I / O(Stream.BeginRead
)。 StreamReader
不直接支持此功能。如果您绝对必须使用它,请编写一个包装器流,它将在基础流上以Read
方式实现BeginRead
并支持超时,取消等。
答案 1 :(得分:1)
尝试将NamedPipeServerStream.ReadMode和/或.TransmissionMode设置为Byte。 无论如何,您都应该将可用的BeginRead / EndRead方法与NamedPipeServerStream一起使用。 这样您就可以自己实现超时逻辑。