[C#] Task.Result가 .GetAwaiter.GetResult ()와 동일합니까?

최근에 많은 비동기 메소드를 사용하는 코드를 읽었지만 때로는 동기식으로 실행해야합니다. 코드는 다음을 수행합니다.

Foo foo = GetFooAsync(...).GetAwaiter().GetResult();

이것과 동일합니까

Foo foo = GetFooAsync(...).Result;



답변

거의 요 한 가지 작은 차이점 : Task실패하면 GetResult()직접 발생한 예외 Task.Result를 throw하고을 throw합니다 AggregateException. 그러나 어느 때에 사용하는 것이 중요 async합니까? 100 배 더 나은 옵션은을 사용하는 것 await입니다.

또한을 사용하지 마십시오 GetResult(). 이것은 컴파일러가 아닌 사용자를위한 것입니다. 그러나 성가신 것을 원하지 않으면 AggregateException사용하십시오.


답변

Task.GetAwaiter().GetResult()이상 선호 Task.Wait하고 Task.Result그것은 그들을 포장보다는 예외를 전파하기 때문에 AggregateException. 그러나 세 가지 방법 모두 교착 상태 및 스레드 풀 기아 문제가 발생할 수 있습니다. 그들은 모두 찬성하여 피해야한다 async/await.

아래 인용하는 이유를 설명 Task.Wait하고 Task.Result단지의 예외 전파 동작을 포함하지 않는 Task.GetAwaiter().GetResult()(인해 “매우 높은 호환성 바”로).

앞에서 언급했듯이 호환성이 매우 높기 때문에 변경 사항을 피할 수 있습니다. 따라서 Task.Wait항상 줄 바꿈의 원래 동작을 유지합니다. 그러나에 의해 사용되는 동기식 차단과 유사한 동작을 원 Task.Wait하지만 원래 예외가에 포함되지 않고 래핑되지 않은 전파를 원하는 일부 고급 상황에 처할 수 있습니다 AggregateException. 이를 위해 작업 대기자를 직접 대상으로 지정할 수 있습니다. ” await task;” 를 쓰면 컴파일러는이를 Task.GetAwaiter()메서드의 사용법으로 변환하여 메서드가있는 인스턴스를 반환합니다 GetResult(). 결함이있는 작업에 사용될 GetResult()경우 원래 예외를 전파합니다 ( ” await task;“의 동작 방식). 따라서 “task.GetAwaiter().GetResult()이 전파 로직을 직접 호출하려는 경우

https://blogs.msdn.microsoft.com/pfxteam/2011/09/28/task-exception-handling-in-net-4-5/

GetResult”은 실제로“작업에 오류가 있는지 확인”을 의미합니다

일반적으로 비동기 작업을 동 기적으로 차단하지 않으려 고 최선을 다합니다. 그러나 그 지침을 위반하는 몇 가지 상황이 있습니다. 드문 조건에서 내가 선호하는 방법은 GetAwaiter().GetResult()작업 예외를에 감싸는 대신 보존하기 때문 AggregateException입니다.

http://blog.stephencleary.com/2014/12/a-tour-of-task-part-6-results.html


답변

https://github.com/aspnet/Security/issues/59

“마지막 말 : 당신은 사용하지 않아야 Task.Result하고 Task.Wait가능한 한 그들은 항상에서 내부 예외를 캡슐화로
AggregateException더 열심히 디버깅하게 일반적인 하나 (하나 이상의 오류가 발생)에 의해 메시지를 교체하더라도 동기 버전 shouldn. 자주 사용 Task.GetAwaiter().GetResult()하지 말고 대신 사용하는 것이 좋습니다. “


답변

또 다른 차이점은 async함수 Task대신에 함수가 반환 되면 Task<T>사용할 수 없다는 것입니다

GetFooAsync(...).Result;

이므로

GetFooAsync(...).GetAwaiter().GetResult();

여전히 작동합니다.

질문의 예제 코드가 사례임을 알고 Task<T>있지만 질문은 일반적으로 요구됩니다.


답변

이미 언급했듯이을 사용할 수 있습니다 await. 당신은 당신이 언급처럼 기적으로 코드를 실행해야하는 경우 .GetAwaiter().GetResult(), .Result또는 .Wait()교착 상태의 위험이다 많은 사람들이 의견 / 답변에서 말했듯이. 우리 대부분은 oneliners를 좋아하기 때문에 이것을 사용할 수 있습니다.Net 4.5<

비동기 메서드를 통해 값을 얻는 방법 :

var result = Task.Run(() => asyncGetValue()).Result;

비동기 메서드를 동 기적으로 호출

Task.Run(() => asyncMethod()).Wait();

사용으로 인해 교착 상태 문제가 발생하지 않습니다 Task.Run.

출처:

https://stackoverflow.com/a/32429753/3850405


답변

작업에 오류가 발생하면 연속 코드가 awaiter.GetResult ()를 호출 할 때 예외가 다시 발생합니다. GetResult를 호출하는 대신 작업의 Result 속성에 간단히 액세스 할 수 있습니다. GetResult 호출의 이점은 작업이 실패하면 AggregateException에 래핑되지 않고 예외가 직접 발생하여 더 간단하고 깔끔한 catch 블록을 허용한다는 것입니다.

제네릭이 아닌 작업의 경우 GetResult ()에는 void 반환 값이 있습니다. 유용한 기능은 전적으로 예외를 다시 발생시키는 것입니다.

출처 : 간단히 말해서 c # 7.0


답변