13

BeginRead를 사용하여 비동기 적으로 데이터를 수신하려면 NetworkStream & TcpClient를 사용하고 있습니다. 이 작업에 타임 아웃을 적용해야하는데, 지정된 시간이 지나면 읽기가 중단됩니다.BeginReceive/BeginRead timeouts

내가 말할 수있는 한 NetworkStream 또는 TcpClient에서 지원되지 않습니다. ReceiveTimeout 속성이 있지만 이것은 동기식 동등한 - '읽기'에만 적용되는 것으로 보입니다.

기본 Socket 클래스도 BeginReceive 메서드에서 시간 제한을 지원하지 않는 것으로 보입니다.

필자는이 문제에 대해 조사한 결과, 다른 백그라운드 스레드를 설정하여 시간 초과 기간 내에 완료되지 않으면 작업을 취소 할 수 있다고 제안했습니다. 이것은 끔찍한 해킹처럼 보입니다. 확실히 더 좋은 방법이 있습니까?

답변

2

비동기 작업을 사용하는 경우 작업을 시작한 스레드가 다른 작업을 수행하기 때문에 작업을 수행하는 유일한 방법입니다. 읽기 작업이 완료 될 때까지 실행 스레드가 차단되므로 시간 제한은 동기 버전에서 사용할 수 있습니다.

작업을 취소하기 위해 백그라운드 스레드를 사용해야하는 경우 비동기식 Begin/End 메서드를 계속 사용하는 것이 중요하지 않습니다. 백그라운드 스레드를 스핀 오프하려면 백그라운드 스레드에서 동기 읽기 작업을 수행 한 다음 ReceiveTimeout을 사용할 수 있습니다.

+1

조엘 취소 백그라운드 스레드를 사용하지 않는 대한 올바른 방향으로 우리를 지적하지만 넣다가 많은 사람들이있다 않는 무엇을, 명확하지 않다 1 스레드 (작업자 설문 조사)가 주기적으로 연결을 끊어 버립니다. 이는 소켓 핸들/etc를 해제하는 데 필요하며 의도적이거나 아닌 서비스 거부 공격과 같은 것이 있으면 중요합니다. – eselk

+0

다른 옵션은 스레드를 사용하지 않는 ['System.Threading.Timer'] (http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx)입니다. – hangar

0

작업이 완료되면 신호를 보내려면 약간의 시간 초과 값을두고 ManualResetEvent을 기다리십시오. 신호가 있기 전에 시간이 초과되면 비동기 작업이 완료되지 않는다는 것을 알게됩니다.

private ManualResetEvent receiveDone = new ManualResetEvent(false); 

receiveDone.Reset(); 
socket.BeginReceive(...); 
if(!receiveDone.WaitOne(new TimeSpan(0, 0, 0, 30))) //wait for 30 sec. 
    throw new SocketException((int)SocketError.TimedOut); 

내부 BeginReceive 콜백 사용

private void ReceiveCallBack(IAsyncResult ar) 
{ 
    /** Use ar to check if receive is correct and complete */ 
    receiveDone.Set(); 
} 
+1

Downvoting은 내가 (순진하게)했던 것과 정확히 일치하고 작동하지 않기 때문에. EndReceive에 대한 호출과 일치하지 않는 모든 BeginReceive 호출은 커널 리소스를 유출합니다. Perfmon과 같은 프로세스 활동을 그래프로 표시하고 비 페이징 풀을 천천히 누출하지 않도록주의하십시오. 이것이 충분히 오래 지속된다면 (내 경우에는 몇 시간), 결국 WSAENOBUFS라는 에러 코드를 가진 예외가 생길 것이다. "시스템에 충분한 버퍼 공간이 없거나 큐가 가득 차서 소켓 작업을 수행 할 수 없습니다." – Anthony

+0

나는 그것을 확인하지 못했지만 예외를 던지기 전에'socket.EndReceive (..) '를 호출하여 문제를 해결할 수는 없을까? EndReceive 호출에 필요한 IAsyncResult는 BeginReceive에 의해 반환됩니다. 귀하의 의견을 Upvoting. 업데이트 주셔서 감사합니다. –

+0

예, 가능합니다. – Anthony

관련 문제