18

을 SetResult작업 FromResult 차이 <strong>가</strong>이의 기능과 의미에 관한 무엇

TaskCompletionSource + SetResult 작업 + FromResult

가 SendAsync 방법에

대? 당신이 원하는 모든 결과에 완성 된 Task<TResult> (또는 하나없이 완료 Task)을 반환하는 경우

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
{ 
    if (request.RequestUri.Scheme != Uri.UriSchemeHttps) 
    { 
     var response = new HttpResponseMessage(HttpStatusCode.Forbidden) {ReasonPhrase = "HTTPS Required"}; 
     var taskCompletionSource = new TaskCompletionSource<HttpResponseMessage>(); 
     taskCompletionSource.SetResult(response); 
     return taskCompletionSource.Task; 
    } 
    return base.SendAsync(request, cancellationToken); 
} 

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
{ 
    if (!request.RequestUri.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase)) 
    { 
     HttpResponseMessage reply = request.CreateErrorResponse(HttpStatusCode.BadRequest, "HTTPS is required for security reason."); 
     return Task.FromResult(reply); 
    } 

    return base.SendAsync(request, cancellationToken); 
} 

답변

28

Task.FromResult는 .NET 4.5에 새로 추가되었습니다. TaskCompletionSource를 만들고 SetResult를 호출하는 도우미 메서드입니다. .NET 4 또는 이전 버전을 사용하는 경우 SetResult를 사용해야합니다.

+0

당신이 ".net 4.5의 새로운 추가 기능"에 대해 언급 한 것은 아무도 언급하지 않은 해결책이었습니다. – Pascal

+2

'Task.FromResult'는'TaskCompletionSource'를 사용하지 않습니다. 'Task.FromResult' 호출 _Special 내부 생성자로 이미 완료된 작업 생성 _. [소스 코드 주석에서] (http://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Task.cs,11a386e7d7cae64a). – Fabio

+0

@Fabio 설명해 주셔서 감사합니다. 아마 이전 버전과의 호환성을위한 방법을 가짜로 만든 MS의 심플 코드를 보았을 것입니다. –

3

, 단순히 Task.FromResult를 사용합니다.

Task.FromResult은 결과와 함께 완료된 작업을 만드는 간단한 도구입니다. TaskCompletionSource은 모든 것을 지원하는 훨씬 강력한 도구입니다. 예외를 설정하고 완료되지 않은 작업을 반환하고 나중에 결과를 설정 할 수 있습니다.

P .: 완성 된 작업을 반환하여 비동기 메서드를 "가짜"로 만드는 것처럼 보입니다. 그것이 최선의 방법이지만, 비동기를 "속이는"것이 실제로 달성하기를 원하는지 확인하십시오.

3

저는 Task.FromResult()이 커버 아래에서 매우 유사한 것을한다고 확신합니다.

TaskCompletionSource의 더 나은 사용 시나리오는 멀티 스레딩을 직접 구현 한 경우입니다. 이 시나리오에서는 백그라운드 스레드가 완료 될 때까지 결과가 설정되지 않고 대기 시간이 TaskCompletionSource.SetResult() 또는 TaskCompletionSource.SetException() 인 호출 대기 태스크를 즉시 반환합니다.

1

내가 Task.FromResult()이 더 효율적이라고 생각하지만 IMO 더 읽을 다음, 할도 수 : async이 방법을 변경하지 않기 때문에,

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
{ 
    if (request.RequestUri.Scheme != Uri.UriSchemeHttps) 
     return new HttpResponseMessage(HttpStatusCode.Forbidden) {ReasonPhrase = "HTTPS Required"}; 
    return await base.SendAsync(request, cancellationToken); 
} 

당신은 여전히베이스의 SendAsync 가상을 무시할 수를 서명.