2011-08-17 98 views
5

我實現了一個模仿串口的DataReceived事件的系統,從TCPClient對象的NetworkStream讀取數據是通過使用BeginRead()方法觸發的,如下所示:在C#中調用BeginRead()後關閉NetworkStream

TcpClient server = new TcpClient(); 
server.Connect(IPAddress.Parse(ip), 10001); 
server.GetStream().BeginRead(buffer, 0, buffer.Length, new AsyncCallback(DataReceived), server.GetStream()); 

從另一個線程調用下面的方法:

private void DataReceived(IAsyncResult result) 
    { 
     res = result; 
     server.GetStream().EndRead(result); 

     //append received data to the string buffer 
     stringBuffer += System.Text.ASCIIEncoding.ASCII.GetString(buffer); 

     //clear the byte array 
     Array.Clear(buffer, 0, buffer.Length); 

     //trigger the parser 
     waitHandle.Set(); 

     server.GetStream().BeginRead(buffer, 0, buffer.Length, new AsyncCallback(DataReceived), buffer); 
    } 

這似乎正常工作。我可以毫無問題地向網絡上的設備發送和接收數據。然而,當我嘗試使用下面的方法,程序崩潰斷開:

public override void disconnect() 
{ 
    server.Close(); 
} 

它引發以下錯誤:

A first chance exception of type 'System.ObjectDisposedException' occurred in System.dll 

我也試圖實現斷開方法如下:

server.GetStream().Close(); 

但這會導致以下錯誤:

A first chance exception of type 'System.InvalidOperationException' occurred in System.dll 

我認爲這與BeginRead()方法已被調用並且EndRead()方法沒有的事實有關。如果是這種情況,我怎樣才能關閉流而不會崩潰?

+1

您需要圍繞EndRead()調用使用try塊,以便捕獲ObjectDisposedException。這是一個可靠的指標,套接字意外關閉。 –

+1

我發現了這個問題。因爲EndRead()和BeginRead()方法調用沒有被try/catch塊包圍,所以我得到一個''System.ObjectDisposedException''。當我關閉流時,這些方法試圖在不再存在的對象上執行。 – isometrik

+0

檢查這些答案,他們是關於相同的問題:http://stackoverflow.com/questions/43096943/how-to-stop-reading-from-networkstream/43101953#comment73305491_43101953 –

回答

1

我只需要調用GetStream一次,並將結果存儲在某處並使用它訪問流。

Stream nstrm = server.GetStream(); 

使用nstrm所有接入到NetworkStream ...

最安全的辦法是維持一個標誌關門的時候,只設置該標誌disconnect()

DataReceived你會後直接EndRead檢查該標誌,如果它被設置做到這一點:

server.Close(); 
nstrm.Close(); 

看到http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.getstream.aspx

編輯 - 按評論:

if (flag2Close) 
{ 
    server.Close(); 
    nstrm.Close(); 
    flag2Close = false; 
} 
else 
{ 
    nstrm.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(DataReceived), buffer); 
} 

順便說一句:對於生產代碼,它需要一些異常處理等。

+0

這工作,但因爲該標誌後檢查調用EndRead(),必須在連接終止之前接收數據。所以,如果我要連接,斷開連接,然後重新連接,它會引發錯誤,因爲連接從未關閉。如果我要連接,斷開連接,發送一些數據,然後重新連接它將工作。 – isometrik

+0

我不太確定我的理解......您處理標誌以關閉TcpClient和Stream的時間完全取決於您 - 您甚至可以在下一個BeginRead之前直接插入檢查,並且只執行BeginRead IF標誌是false ...請參閱我上面的編輯 – Yahia

+0

是的,但是當調用BeginRead()方法時,它會調用DataReceived方法並阻塞,直到接收到數據。這意味着該標誌將不會被檢查,直到接收到數據時發生的下一次迭代。 – isometrik

相關問題