命名管道服务器读取超时

Maj*_*cRa 8 c# ipc named-pipes

使用C#NamedPipeServerStream时,如果客户端没有发送任何消息结束模式(如服务器使用ReadLine()读取时为\ r \n)NamedPipeServerStream Read方法将永远等待,并且没有Abort()或Interupt()方法将在那个线程上工作.

从以下版本开始:
1)NamedPipeServerStream不支持Stream.ReadTimeout
2)Abort()或Interupt()在线程
3 上不起作用)NamedPipeServerStream.Disconnect()nether work
目前还不清楚,如何在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]);
        }
    }
Run Code Online (Sandbox Code Playgroud)

那么如何在NamedPipeServerStream读取操作上设置超时?

Ant*_*hyy 4

由于您在消息模式下运行管道,因此您应该首先将整个消息读入缓冲区byte[]或内存流,然后确定其是否有效并对其进行解码。管道消息有一定的长度。它无法显式检索,但当您从消息模式管道读取时它会显示。如果消息中仍有未读字节,Win32ReadFile将失败,然后返回以指示消息已结束。此后,对 的调用将被阻止,直到有新消息可用。自然不知道这些并阻塞您的线程。ERROR_MORE_DATATRUEReadFileStreamReader

更新:要实现超时,请使用异步 I/O ( Stream.BeginRead)。StreamReader不直接支持这一点。如果您绝对必须使用它,请编写一个包装器流,它将在底层流上Read实现并支持超时、取消等。BeginRead