使用 C# NamedPipeServerStream 时,如果客户端不发送任何消息结束模式(例如服务器使用 ReadLine() 读取时的 \r\n),NamedPipeServerStream Read 方法将永远等待,并且不会出现 Abort() 或 Interupt() 方法在该线程上工作。
Since:
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读取操作的超时时间呢?
由于您在消息模式下运行管道,因此您应该首先将整个消息读入byte[]
缓冲区或内存流以及then判断它是否有效并对其进行解码。管道消息有一定的长度。它无法显式检索,但当您从消息模式管道读取时它会显示。 Win32ReadFile
失败了ERROR_MORE_DATA
如果消息中仍有未读字节,则返回TRUE
表示消息已结束。此后,致电ReadFile
将阻塞,直到有新消息可用。StreamReader
自然不知道这些并阻塞您的线程。
Update:要实现超时,请使用异步 I/O (Stream.BeginRead
). StreamReader
不直接支持这一点。如果您绝对必须使用它,请编写一个包装器流来实现Read
按照BeginRead
在底层流上并支持超时、取消等。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)