최근에 많은 비동기 메소드를 사용하는 코드를 읽었지만 때로는 동기식으로 실행해야합니다. 코드는 다음을 수행합니다.
Foo foo = GetFooAsync(...).GetAwaiter().GetResult();
이것과 동일합니까
Foo foo = GetFooAsync(...).Result;
async
/ await
방법)
최근에 많은 비동기 메소드를 사용하는 코드를 읽었지만 때로는 동기식으로 실행해야합니다. 코드는 다음을 수행합니다.
Foo foo = GetFooAsync(...).GetAwaiter().GetResult();
이것과 동일합니까
Foo foo = GetFooAsync(...).Result;
async
/ await
방법)
답변:
거의 요 한 가지 작은 차이점 : Task
실패하면 GetResult()
직접 발생한 예외 Task.Result
를 throw하고을 throw합니다 AggregateException
. 그러나 어느 때에 사용하는 것이 중요 async
합니까? 100 배 더 나은 옵션은을 사용하는 것 await
입니다.
또한을 사용하지 마십시오 GetResult()
. 이것은 컴파일러가 아닌 사용자를위한 것입니다. 그러나 성가신 것을 원하지 않으면 AggregateException
사용하십시오.
async Task
단위 테스트를 지원 하며 얼마 동안 있습니다.
The 100x better option is to use await.
만약 내가 await
앞에 때릴 수 있다면 나는 이와 같은 진술을 싫어한다 . 나는 자주 나에게 무슨 일 같은 비 비동기 코드에 대한 작업을 비동기 코드를 얻으려고하지만, 많은 자 마린에를, 내가 좋아하는 일을 사용할 필요 결국 ContinueWith
은 UI를 교착하지 수 있도록하기 위해 많은. 편집 : 나는 이것이 오래되었다는 것을 알고 있지만, 당신이 단지 사용할 수없는 상황에 대한 대안없이 이것을 언급하는 답을 찾는 것을 완화시키지 않습니다 await
.
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
Task.GetAwaiter().GetResult()
으로와 같습니다 await task
. 메서드를 표시 할 수없는 경우 첫 번째 옵션을 사용한다고 가정합니다 async
(예 : 생성자). 그 맞습니까? 그렇다면, 그것은 상단 응답과 충돌 @ It'sNotALie
Task.GetAwaiter().GetResult()
와 동일 Task.Wait
하며 Task.Result
(세 가지 모두 동 기적으로 차단되고 교착 상태 Task.GetAwaiter().GetResult()
가 발생할 수 있음) 대기 작업의 예외 전파 동작이 있습니다.
https://github.com/aspnet/Security/issues/59
"마지막 말 : 당신은 사용하지 않아야
Task.Result
하고Task.Wait
가능한 한 그들은 항상에서 내부 예외를 캡슐화로AggregateException
더 열심히 디버깅하게 일반적인 하나 (하나 이상의 오류가 발생)에 의해 메시지를 교체하더라도 동기 버전 shouldn. 자주 사용Task.GetAwaiter().GetResult()
하지 말고 대신 사용하는 것이 좋습니다. "
Task.WhenAll(task1, task2).GetAwaiter().GetResult();
.
또 다른 차이점은 async
함수 Task
대신에 함수가 반환 되면 Task<T>
사용할 수 없다는 것입니다
GetFooAsync(...).Result;
이므로
GetFooAsync(...).GetAwaiter().GetResult();
여전히 작동합니다.
질문의 예제 코드가 사례임을 알고 Task<T>
있지만 질문은 일반적으로 요구됩니다.
Result
하는 GetIntAsync()
을 사용 하고 Task<int>
있습니다 Task
. 내 대답을 다시 읽어 보시기 바랍니다.
GetFooAsync(...).Result
안에 넣을 수 없다는 것을 이해했습니다 Task
. C #에는 void 속성이 없으므로 (이것은 속성이므로) 이제는 의미 Task.Result
가 있지만 void 메서드를 호출 할 수도 있습니다.
이미 언급했듯이을 사용할 수 있습니다 await
. 당신은 당신이 언급처럼 기적으로 코드를 실행해야하는 경우 .GetAwaiter().GetResult()
, .Result
또는 .Wait()
교착 상태의 위험이다 많은 사람들이 의견 / 답변에서 말했듯이. 우리 대부분은 oneliners를 좋아하기 때문에 이것을 사용할 수 있습니다.Net 4.5<
비동기 메서드를 통해 값을 얻는 방법 :
var result = Task.Run(() => asyncGetValue()).Result;
비동기 메서드를 동 기적으로 호출
Task.Run(() => asyncMethod()).Wait();
사용으로 인해 교착 상태 문제가 발생하지 않습니다 Task.Run
.
출처:
작업에 오류가 발생하면 연속 코드가 awaiter.GetResult ()를 호출 할 때 예외가 다시 발생합니다. GetResult를 호출하는 대신 작업의 Result 속성에 간단히 액세스 할 수 있습니다. GetResult 호출의 이점은 작업이 실패하면 AggregateException에 래핑되지 않고 예외가 직접 발생하여 더 간단하고 깔끔한 catch 블록을 허용한다는 것입니다.
제네릭이 아닌 작업의 경우 GetResult ()에는 void 반환 값이 있습니다. 유용한 기능은 전적으로 예외를 다시 발생시키는 것입니다.
출처 : 간단히 말해서 c # 7.0
GetResult
" 문서 에서이 유형과 그 멤버는 컴파일러가 사용하도록되어 있습니다." 다른 사람이 사용해서는 안됩니다.