2012-02-16 4 views
4
나는 보통 비동기 콜백을 통해 UdpClient로부터 데이터를 수신하고

: 내가 메인 스레드에 UdpClient를 Close()UdpClient가 폐쇄/폐기되었는지 어떻게 알 수 있습니까?

private void OnUdpData(IAsyncResult result) 
{ 
    byte[] data = _udpReceive.EndReceive(result, ref _receiveEndPoint); 

    //Snip doing stuff with data 

    _udpReceive.BeginReceive(OnUdpData, null); 
} 

가 콜백 화재 내가 기대하는 것처럼,하지만이 시점 _udpReceive에 이미 배치되어 내가 얻을 ObjectDisposedException 전화를 걸어 EndReceive()으로 전화하십시오. 나는 단지 빈 버퍼를 얻을 것으로 예상했다.

이 문제를 해결하는 올바른 방법은 무엇입니까? UdpClient의 멤버가 있습니까? 사용하려고하기 전에 확인할 수 있습니까? 또는 try{}에 모두 랩핑하고 ObjectDisposedException을 잡을 수있는 유일한 방법입니까? 정상적인 닫기를 위해 꽤 심술 것 같습니다.

답변

4

이것은 전적으로 설계된 것입니다. 예외적 인 일을했지만 데이터 수신을 기대한다고해도 소켓을 닫았습니다. 그래서 예외가 생깁니다. .NET 프레임 워크 항상은 비동기 호출이 완료되고 EndXxx()를 호출 할 때 콜백에서 신호 중단 이유가 신호되는지 확인합니다. 좋은 생각은 콜백과 관련된 모든 상태를 정리할 수있게 해줍니다.

전송이 완료 될 때까지 기다리지 않고 예외적으로 만들 수 있습니다. BeginReceive() 및 을 호출 한 다음 소켓을 닫지 마십시오. 그러나 이것이 항상 실용적인 것은 아니며 때로는 일찍 종료되기를 원합니다. 문제는 아니며 단순히 ObjectDisposedException을 catch하여 빠져 나오십시오. 물론 일 때 와이어의 다른 쪽 끝에서 앱이 어떻게되는지 생각해보십시오. 이후에 전송되는 내용은 비트 버킷에 빠져서 찾아 낼 방법이 없습니다.

5

처분 여부를 확인할 수 있습니다. UdpClient가 삭제되면 클라이언트는 null로 설정됩니다.

private void OnUdpData(IAsyncResult result) 
{ 
    if (_udpReceive.Client == null) 
     return; 
    byte[] data = _udpReceive.EndReceive(result, ref _receiveEndPoint); 

    //Snip doing stuff with data 

    if (_udpReceive.Client == null) 
     return; 
    _udpReceive.BeginReceive(OnUdpData, null); 
} 

별도의 스레드를 닫는 때문에 경쟁 조건으로 끝낼 수 있지만. ObjectDisposedException 및 SocketException을 잡는 것이 가장 좋습니다.

private void OnUdpData(IAsyncResult result) 
{ 
    try 
    { 
     byte[] data = _udpReceive.EndReceive(result, ref _receiveEndPoint); 

     //Snip doing stuff with data 

     _udpReceive.BeginReceive(OnUdpData, null); 
    } 
    catch (Exception e) 
    { 
     //You may also get a SocketException if you close it in a separate thread. 
     if (e is ObjectDisposedException || e is SocketException) 
     { 
      //Log it as a trace here 
      return; 
     } 
     //Wasn't an exception we were looking for so rethrow it. 
     throw; 
    } 
} 
+0

콜백은 'EndReceive'를 호출해야 할 책임을 해 줍니까? 제 인상은 리소스를 묶지 않는 (예를 들어'Control.BeginInvoke'의 반환 값) 몇몇 유형의'IAsyncResult '를 제외하고는'BeginXX'마다 * 항상 * EndXX를 호출한다고 가정합니다. 예외를 잡는 예외는'EndReceive' 연산이 실패했다는 신호가 아니라 수신 성공을 초래 한 예외를 중계하는 "성공적인"EndReceive 호출의 결과입니다. – supercat

+0

BeginX에서 데이터를 가져 오기 위해 EndX가 호출되지 않습니까? 이 경우 리턴은 괜찮습니다. EndReceive는 동일한 것을 검사하고 어쨌든 처분 된 예외를 던집니다. – Will

관련 문제