2011-09-28 2 views
11

TcpClient에서 표준 BeginRead 및 EndRead 메서드를 사용하고 Task.Factory.FromAsync를 사용할 때 매우 유사한 코드가 있습니다.Task.Factory.FromAsync와 BeginX/EndX의 차이점은 무엇입니까?

다음은 몇 가지 예입니다. 오류 처리 코드가 표시되지 않았습니다.

Task.Factory.FromAsync : 그러면 BeginRead 및 EndRead와 콜백의

private void Read(State state) 
{ 
    Task<int> read = Task<int>.Factory.FromAsync(state.Stream.BeginRead, state.Stream.EndRead, state.Bytes, state.BytesRead, state.Bytes.Length - state.BytesRead, state, TaskCreationOptions.AttachedToParent); 

    read.ContinueWith(FinishRead); 
} 

private void FinishRead(Task<int> read) 
{ 
    State state = (State)read.AsyncState; 

    state.BytesRead += read.Result; 
} 

표준 사용 :

private void Read(State state) 
{ 
    client.BeginRead(state.Bytes, state.BytesRead, state.Bytes.Length - state.Bytes.Read, FinishRead, state); 
} 

private void FinishRead(IAsyncResult async) 
{ 
    State state = (State)async.AsyncState; 

    state.BytesRead += state.Stream.EndRead(async); 
} 

이 모두 잘 작동하지만 난 그들의 차이 궁금합니다. 둘 모두에 대한 코드 행은 거의 동일하며 둘 다 똑같은 기능을 수행하고 동일한 효율성을 갖는 것처럼 보입니다. 어느 것이 더 낫습니까? 생산 코드에서 무엇을 볼 것입니까?

답변

14

나는 차라리 Task<T> 기반의 코드를 볼 것입니다 :

그것은 더 쉽게 구성을 제공
  • ; 예를 들어, Task<T> 작업의 콜렉션을 취하는 메소드를 작성하는 것이 합리적으로 쉽고, 해당 타스크의 다수결을 나타내는 다른 타스크를 리턴합니다. 마찬가지로 일련의 작업 중 하나가 완료 될 때까지 기다릴 수 있습니다.
  • 연속 실행이보다 유연하게 예약됩니다.
  • 작업 자체가 유형 안전성과 다소 빈약 한 IAsyncResult 유형보다 많은 정보를 반환 할 수 있습니다. BeginRead이 반환합니다.
  • Begin/End 모델을 사용하는 것보다 오류 처리 및 작업 취소를 지정하는 것이 더 간단합니다. 기본적으로 현대적인 코드가 실행이

을 활용하기 위해 당신의 코드베이스가 이미 pervasively Task<T>를 사용하는 경우, 그것은 훨씬 쉬울 것이다 -

  • Task<T> 비동기/await를 함께 C# 5에서 더 나은 언어 지원을 받고있다 .NET 4, Task<T>은 진행중인 작업을 표현하는 관용적 인 방법입니다. 이전의 시도보다 훨씬 더 풍부한 환경에서 작업 할 수 있습니다. 기회가 있으면 받아 들일 것입니다. 분명히 .NET 3.5 또는 그 이전 버전을 사용한다면 인생은 조금 더 어려워 질 것입니다. 그러나 질문을 할 때 Task<T>이 옵션 일 것이라고 가정합니다 ...

  • +1

    답장을 보내 주셔서 감사합니다! 나는 아직도 약간 혼란 스럽다. BeginRead는 콜백이 블로킹보다는 IO 완료 포트를 사용하기 때문에 매우 효율적이라는 것을 알고 있습니다. ContextWith는 효율성면에서 동일하지 않으며 EndRead가 실행되었을 때만 실행됩니다. 또한 더 나은 오류 처리를 지원하는 방법에 대해 자세히 설명 할 수 있습니까? 각 코드 샘플의'state.BytesRead + ='줄에서도 동일한 try-catch를 수행해야합니까? –

    +2

    @RyanPeschel : 예, 차단하지 않습니다. 그렇지 않으면 무의미합니다. 아니요, 오류가 발생해도 실행을 계속할 것인지, 취소시 실행할 것인지를 지정하고 성공을 위해 실행할 때를 지정 할 수 있으므로 동일한 try/catch는 필요하지 않습니다. ContinueWith의 오버로드를 살펴보십시오. 또한 결과를 얻으려고하지 않고도 태스크의 상태를 테스트 할 수 있습니다 (Task.Status를보십시오). 기본적으로 모든 것이 훨씬 풍부합니다. C# 5의 비동기 지원은 훌륭합니다. –

    +0

    과부하를 확인하고 있지만 현재 무엇을보고 있는지 잘 모르겠습니다. 오류/취소가있을 때 실행할 메소드를 어떻게 지정할 수 있습니까? –

    관련 문제