C# TCP客户端和网络流处理问题

C# TCP客户端和网络流处理问题,c#,stream,idisposable,objectdisposedexception,C#,Stream,Idisposable,Objectdisposedexception,我使用这段代码处理与服务器的连接,并从客户端读取数据 using(var client = _listener.EndAcceptTcpClient(ar)) { var clientStream = client.GetStream(); // Get the request message Messages.ReceiveMessage(clientStream, msg => ProcessRequest(msg, clientStr

我使用这段代码处理与服务器的连接,并从客户端读取数据

using(var client = _listener.EndAcceptTcpClient(ar))
{
        var clientStream = client.GetStream();
        // Get the request message 
        Messages.ReceiveMessage(clientStream, msg => ProcessRequest(msg, clientStream));
}
现在,ReceiveMessage方法对作为参数传递的流调用
BeginRead()
,但我得到了一个ObjectDisposedException

我知道一个解决方案是在我不再需要流时调用stream.Dispose(),但我确实在寻找一个解决方案,在这个解决方案中,我可以使用子句来维护
的使用

谢谢

您可以这样做:

using (var client = _listener.EndAcceptTcpClient(ar))
{
    var clientStream = client.GetStream();

    using (var eh = new ManualResetEvent(false))
    {
        // Get the request message 
        Messages.ReceiveMessage(clientStream, msg =>
            {
                ProcessRequest(msg, clientStream);
                eh.Set();
            });

        eh.WaitOne();
    }
}
一个警告:如果有任何合理的地方(一个类实例)存储ManualResetEvent,以便重用它,那么就这样做——因为创建/销毁很多这样的事件可能有点麻烦

还请注意,根据您在文章中描述的行为,我假设ReceiveMessage()是一个异步操作。

您可以这样做:

using (var client = _listener.EndAcceptTcpClient(ar))
{
    var clientStream = client.GetStream();

    using (var eh = new ManualResetEvent(false))
    {
        // Get the request message 
        Messages.ReceiveMessage(clientStream, msg =>
            {
                ProcessRequest(msg, clientStream);
                eh.Set();
            });

        eh.WaitOne();
    }
}
一个警告:如果有任何合理的地方(一个类实例)存储ManualResetEvent,以便重用它,那么就这样做——因为创建/销毁很多这样的事件可能有点麻烦


还请注意,根据您在文章中描述的行为,我假设ReceiveMessage()是一个异步操作。

这里有两种可能性

首先,您可以使用这个异步进程并阻塞它,直到它完成为止,这样您就可以保留using语句。这就是方法

或者,您可以删除using语句,并自行处理客户机变量。这似乎比使用编译器的语法更麻烦,但它确实提供了一个优势,允许您维护当前在这种情况下试图利用的异步行为,并且消除了对块的需要。但是,这将要求您存储变量,并将其自己处置在适当的位置(可能在委托末尾,但也可能需要稍后检查,以防从未调用委托)


C#中的“using”语句很好,但也有不合适的情况,这可能是其中之一(如果需要保留异步行为)。

这里有两种可能性

首先,您可以使用这个异步进程并阻塞它,直到它完成为止,这样您就可以保留using语句。这就是方法

或者,您可以删除using语句,并自行处理客户机变量。这似乎比使用编译器的语法更麻烦,但它确实提供了一个优势,允许您维护当前在这种情况下试图利用的异步行为,并且消除了对块的需要。但是,这将要求您存储变量,并将其自己处置在适当的位置(可能在委托末尾,但也可能需要稍后检查,以防从未调用委托)


C#中的“using”语句很好,但也有不合适的情况,这可能是其中之一(如果需要保留asynchronous行为)。

ManualResetEvent实现IDisposable,因此此模式应包装在using语句中。不过,这“中断”了数据的异步处理,因为在异步进程完成之前,基本上是阻塞的。这可能不是所有情况下都需要的。我在给定的限制范围内回答了这个问题。:-)Joe关于使用()的看法是正确的。ManualResetEvent实现了IDisposable,因此此模式应包装在using语句中。但这“中断”了数据的异步处理,因为在异步过程完成之前,基本上是阻塞的。这可能不是所有情况下都需要的。我在给定的限制范围内回答了这个问题。:-)不过,Joe使用ManualResetEvent是对的。