2011-08-17 2 views
5

다음과 같이 BeginRead() 메서드를 사용하여 TCPClient 객체의 NetworkStream에서 데이터를 읽는 방식으로 직렬 포트의 DataReceived 이벤트를 모방 한 시스템을 구현했습니다. 다른 스레드에서 다음 메소드를 호출C#에서 BeginRead()를 호출 한 후 네트워크 스트림 닫기

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); 
    } 

이 제대로 작동하려면 나타납니다. 네트워크상의 장치로 데이터를 보내고받을 수 있습니다. 그러나, 나는 다음과 같은 방법, 프로그램 충돌 사용하여 분리 할 때 : 나는 또한 다음과 같이 분리 방법을 구현하는 시도

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

:

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

그것은 다음과 같은 오류가 발생을

server.GetStream().Close(); 

이 결과로 다음 오류가 발생합니다.

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

이 작업은 BeginRead() 메서드가 호출되었고 EndRead() 메서드가 수행되지 않았다고 가정합니다. 그렇다면 어떻게 충돌없이 스트림을 닫을 수 있습니까?

+1

EndRead() 호출에서 try 블록을 사용해야 ObjectDisposedException을 catch 할 수 있습니다. 소켓이 예기치 않게 닫힌다는 안정적인 표시입니다. –

+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을 호출하고 결과를 어딘가에 저장하고 스트림에 액세스하는 데 사용합니다. 모든 사용 nstrmNetworkStream에 액세스

Stream nstrm = server.GetStream(); 

...

안전한 방법은 폐쇄 그냥 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); 
} 

BTW : 생산 코드를 위해 예외 처리 등이 필요합니다.

+0

EndRead()가 호출되면 연결을 종료하기 전에 데이터를 수신해야합니다. 따라서 연결을 끊었다가 다시 연결하면 연결이 끊어지지 않았기 때문에 오류가 발생합니다.연결하고 연결을 끊었다가 데이터를 보낸 다음 다시 연결하면 작동합니다. – isometrik

+0

정말 잘 모르겠다 ... TcpClient를 닫기 위해 플래그를 처리하는 지점과 스트림은 전적으로 당신에게 달렸다. 다음 BeginRead 전에 직접 체크를하고 BeginRead 만 실행해도된다. 거짓입니다 ... 위의 편집을 참조하십시오. – Yahia

+0

예. BeginRead() 메서드가 호출되면 DataReceived 메서드가 호출되고 데이터가 수신 될 때까지 차단됩니다. 즉, 데이터를 수신 할 때 발생하는 메소드의 다음 반복 때까지 플래그가 점검되지 않습니다. – isometrik

관련 문제