C#网络编程和资源使用

时间:2009-02-01 10:23:40

标签: c# .net network-programming using-statement

我一直在研究如何最好地用C#编写“正确”的网络代码。

我已经看过很多使用C#的“using”语句的例子,我认为这是一个很好的方法,但是我看到它与各种表达方式的使用不一致。

例如,假设我有一些这样的代码:

TcpClient tcpClient = new TcpClient("url.com", 80);
NetworkStream tcpStream = tcpClient.GetStream();
StreamReader tcpReader = new StreamReader(tcpStream);
StreamWriter tcpWriter = new StreamWriter(tcpStream);

显然,这段代码非常不稳定。所以,我已经看到一些代码将使用放在tcpClient上,这似乎很好。但是,NetworkStream是否还有需要清理的资源?那么StreamReader / Writer呢?

我是否需要在嵌套的using语句中包装所有4个语句?

如果是这样的话,处理时间会发生什么? StreamWriter不会关闭流并因此关闭套接字吗?然后当StreamReader,然后是NetworkStream,然后TcpClient各自经过他们的处理时会发生什么呢?

这提出了另一个问题。 StreamReader和StreamWriter都由同一个流组成,谁拥有它?难道他们都不认为他们拥有它,因此都会试图摧毁它吗?或者框架是否知道流已经被破坏并且只是默默地忽略它?

看起来似乎只对链中的最后一个语句使用using语句,但是如果在GetStream()中抛出异常会发生什么?我不认为它会正确清理套接字,所以看起来多余的使用是必要的,以确保不会发生这种情况。

有没有人知道有关.net网络编程的最新书籍,还有c#,其中包括有关异常处理和资源管理的章节?或者也许网上有好文章?我能找到的所有书籍都来自.NET 1.1时代(Microsoft .NET Framework的网络编程,.NET中的网络编程等),所以这看起来像是一个需要一些好资源的话题。

编辑:

请不要让Marc非常好的评论阻止其他人对此发表评论:)

我想听听任何人在资源管理方面的建议或意见,特别是在异步使用方面。

3 个答案:

答案 0 :(得分:14)

通常,对象应在内部处理多个Dispose()调用,并且只执行一次主代码;所以多次获得Dispose() d的流通常不是问题。就个人而言,我会在那里使用很多using;请注意,您不需要缩进/嵌套(除非不同的级别具有不同的生命周期):

using(TcpClient tcpClient = new TcpClient("url.com", 80))
using(NetworkStream tcpStream = tcpClient.GetStream())
using(StreamReader tcpReader = new StreamReader(tcpStream))
using(StreamWriter tcpWriter = new StreamWriter(tcpStream))
{
   ...
}

正如您所说,这可确保在初始化期间发生错误时,仍可正确清除所有内容。这也确保每个级别都有机会(以正确的顺序)正确处理任何缓冲的数据等。

重新拥有; NetworkStream首先实际上是一个奇怪的...大多数流要么输入 xor 输出。 NetworkStream弯曲一些规则并将两个方向填充到一个API中;所以这是一个例外...通常所有权会更清楚。此外,许多包装器都有一个标志来确定它们是否应该关闭包装的流。 StreamReader没有,但有些(例如GZipStreamleaveOpen ctor选项)。如果您不想流转所有权,这是一个选项 - 或者使用非关闭流中介 - 一个是hereNonClosingStream或类似的)。

重新预订;我拿了一份“C#中的TCP / IP套接字:程序员实用指南”(here) - 足够但不是很好。

答案 1 :(得分:0)

如果一个对象支持IDisposable,最好将它放在using {}块中,因为dispose方法会自动为你调用。这也减少了您的代码。重要的是要注意使用'using'不处理任何异常。如果你想处理任何错误,你仍然必须这样做。一旦使用块超出范围,您的对象也是如此。

Old Style Code

object obj;

try
{
   obj= new object();
   //Do something with the object
}
catch
{
   //Handle Exception
}
finally
{

  if (obj != null)
  {  
     obj.Dispose();
  }
}  

Newer Style Code

try
{   
  using (object obj = new object())
  {
     //Do something with the object
  }
catch
{
   //Handle Exception
}

答案 2 :(得分:-1)

套接字怎么样? 可以这样做:

serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.Connect(serverEndPoint, m_NegotiationPort);
.
.
.
serverSocket.Close();

或更好

using (Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
{
.
.
.
}