2013-02-25 5 views
3

이 질문은 디자인이나 패턴 및 사용에 대한 질문이 아닙니다. 이 질문의 핵심은 스레드와 블로킹에 관한 현상입니다.장기 실행 차단 방법. 블로킹, 슬리핑, 시작/종료 및 비동기 간의 차이

이 예는 동일한 작업을 연속적으로 수행하도록 설계된 차단 방법에 적용됩니다. 이 경우 네트워크 스트림에서 읽기 또는 쓰기를 차단합니다. 메서드들 사이의 스레딩과 퍼포먼스와 관련하여 장면 뒤에 어떤 차이가 있습니까?

내 생각에 아래의 각 메서드는 스레드를 만들거나 풀링 된 스레드를 사용합니다. 그런 다음 읽을 데이터가있을 때까지 스레드를 차단합니다. 그런 맥락에서, 스레딩, 퍼포먼스, 확장성에 관해서는 상당한 차이가 있습니까?

현재 서버 응용 프로그램을 만들고 있습니다. 이 응용 프로그램에는 1000 개의 클라이언트가 tcp 연결을 만듭니다. 이러한 연결은 열린 채로 유지되어 소량의 데이터를 자주주고받습니다. 모델 A를 사용하는 것이 가장 쉽고 유지하기 쉽기 때문에 모델 A를 사용하려고합니다. 어떤 패턴이 선택 되더라도 1000 스레드로 끝날 것인가?

이러한 방법은 스트리밍 읽기, 시간 초과 및 예외 처리없이 사용할 수있는 구조가 아닌 아이디어를 제공하기위한 것입니다.

방법 A :

Task.Factory.StartNew(ReadMessage,TaskCreationOptions.LongRunning); 
private void ReadMessage() 
{ 
    while(true) 
    { 
     if(TcpClient.DataAvailable) 
      TcpClient.Read(); 
     else 
      Thread.Sleep(1); 
    } 
} 

방법 C 자 :

Task.Factory.StartNew(ReadMessage,TaskCreationOptions.LongRunning); 
private void ReadMessage() 
{ 
    while(true) 
    { 
     TcpClient.Read(); 
    } 
} 

방법 B 차단 재귀 시작/종료

private void ReadMessage() 
{ 
     stream.BeginRead(readCallBack) 
} 
private void readCallBack() 
{ 
     stream.EndRead(); 
     stream.BeginRead(readCallBack) 
} 

방법 D : BCL socket.ReceiveAsync에서 비동기 ()

private void readCallBack() 
{ 
    while(true) 
    { 
     await socket.ReceiveAsync(eventArgs); 
    } 
} 

방법 E : 읽기를 차단와 비동기 방식은

private async Task<byte[]> ReceiveAsync() 
{ 
    return await Task.Factory.StartNew(() => TcpClient.Read()); 
} 

답변

1

내 가정은 각 점이다 (대신하여 BCL에서 소켓의 exstendion 내장 사용하는 사용자 정의 메소드를 호출하는 방법 D를 사용하지만입니다) 아래의 메서드는 스레드를 만들거나 풀링 된 스레드를 사용합니다. 그런 다음 읽을 데이터가있을 때까지 스레드를 차단합니다.

전혀 아닙니다. 처음 두 예제는 스레드를 차단하지만 두 번째 예제는 비동기입니다.

비동기 메서드는 작업을 OS에 대기시킨 다음이 경우 I/O 완료 포트에서 콜백을 기다리는 방식으로 작동합니다. 따라서 읽기가 보류 중일 때는 사용중인 스레드가 없습니다.

비동기 방식은 많은 스레드를 사용하지 않으므로 확장 성이 뛰어납니다.

마지막 예 (async)는 첫 번째 예와 마찬가지로 간단하며 Rx 또는 TPL 데이터 흐름을 사용하지 않는 한 내가 권장하는 방법입니다. 소켓 통신을 수행 할 때, 끊어진 연결 감지와 같은 오류 처리를 고려할 때 비동기 통신이 명확한 방법입니다.

+0

설명해 주셔서 감사합니다. 정말 도움이되었습니다.마지막 질문은 방법 D와 새로운 방법 E 사이에 차이점이 있습니까? 방법 E는 스레드를 차단하지 않고 대신 IOCP를 사용한다는 점에서 성능이 우수할까요? –

+1

'async' 메소드에서 입출력 호출을 막는 것은 결코 좋은 생각이 아닙니다. 메서드 E는 호출 스레드를 차단하고 IOCP를 사용하지 않습니다. 메서드 C와 D는 IOCP를 사용하고 호출 스레드를 차단하지 않습니다. –

+0

제안 사항대로 E 방식을 수정했습니다. 나는 그 대답은 스레드를 차단하고 IOCP를 사용하지 않을 것이라는 점에서 상상된다. –