TcpClient和NetworkStream处理问题

时间:2009-07-20 18:42:35

标签: c# stream idisposable objectdisposedexception

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

using(var client = _listener.EndAcceptTcpClient(ar))
{
        var clientStream = client.GetStream();
        // Get the request message 
        Messages.ReceiveMessage(clientStream, msg => ProcessRequest(msg, clientStream));
}

现在,ReceiveMessage方法调用作为参数传递的Stream上的BeginRead(),但是我收到了ObjectDisposedException。

我知道解决方案是在我不再需要Stream时调用stream.Dispose(),但我真的在寻找一个可以保持using子句使用的解决方案。

由于

2 个答案:

答案 0 :(得分:3)

这里有两种可能性。

首先,您可以使用此异步进程并阻塞直到它完成,从而允许您保留using语句。这是方法suggested by Ben M here

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

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

答案 1 :(得分:2)

你可以这样做:

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()是异步操作。