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是对的。