2009-02-01 56 views
7

我一直在做很多關於如何最好地在C#中編寫「正確的」網絡代碼的研究。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怎麼樣?

我是否需要在嵌套使用語句中包裝所有4個語句?

如果是這樣,當時間到來時會發生什麼? StreamWriter不會關閉流並因此關閉套接字?那麼當StreamReader,然後是NetworkStream,然後TcpClient每個都通過它們的處置時會發生什麼?

這引出了另一個問題。是否同時擁有StreamReader和StreamWriter?誰擁有它?難道他們都認爲自己擁有它,並且會因此而試圖摧毀它嗎?或者,框架是否知道該流已經被破壞,只是默默地忽略它?

它幾乎看起來像using語句只對鏈中的最後一個語句是必需的,但是如果在GetStream()中引發異常會發生什麼?我不認爲它會妥善清理套接字,所以看起來多餘的使用是必要的,以確保不會發生。

有沒有人知道任何關於.net網絡編程的最新書籍,還有c#,包括有關異常處理和資源管理的章節?或者,也許在網上有好的文章?我可以找到的所有書籍都來自.NET 1.1時代(Microsoft .NET Framework的網絡編程,.NET中的網絡編程等),所以這似乎是一個需要一些好資源的主題。

編輯:

請,不要讓馬克的很好的評論,從評論這:)阻止別人

我想聽聽資源管理別人的人建議書或意見,特別是關於異步使用。

回答

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沒有,但有一些(如GZipStream,其中有leaveOpen ctor選項)。如果您不想流動所有權,這是一個選項 - 或者使用非結束流中介 - 一個是hereNonClosingStream或類似)。

重書;我拿起了一份「C#中的TCP/IP套接字:程序員實用指南」(here) - 適當但不是很好。

+0

感謝您的反饋意見。這主要是我懷疑的。 我同意,NetworkStream是一個奇怪的。我不確定創建獨立的讀寫流是否會有問題,但它是什麼。感謝您的書推薦。 – 2009-02-01 11:11:20

0

如果一個對象支持IDisposable,最好將它放在一個using塊中,因爲dispose方法會自動爲您調用。這也可以減少代碼。注意使用「使用」不處理任何異常是很重要的。如果你想處理任何錯誤,你仍然必須這樣做。一旦使用塊超出了範圍,你的對象也是如此。

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 
} 
-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) 
{ 
. 
. 
. 
}