개발관련/other

C #의 동기 메서드에서 비동기 메서드를 호출하는 방법

Rateye 2021. 12. 16. 09:36
728x90
반응형
질문 : C #의 동기 메서드에서 비동기 메서드를 호출하는 방법은 무엇입니까?

동기 메서드에서 호출하려는 public async void Foo() 지금까지 MSDN 설명서에서 본 모든 것은 비동기 메서드를 통해 비동기 메서드를 호출하는 것이지만 내 전체 프로그램은 비동기 메서드로 빌드되지 않았습니다.

이것이 가능할까요?

다음은 비동기 메서드에서 이러한 메서드를 호출하는 한 가지 예입니다.
연습 : Async 및 Await를 사용하여 웹 액세스 (C # 및 Visual Basic)

이제 동기화 메서드에서 이러한 비동기 메서드를 호출하는 방법을 살펴보고 있습니다.

답변

비동기 프로그래밍은 코드베이스를 통해 "성장"합니다. 그것은 좀비 바이러스와 비교 되었습니다. 가장 좋은 해결책은 성장을 허용하는 것이지만 때로는 불가능합니다.

부분 비동기 코드 기반을 처리하기 위해 Nito.AsyncEx 라이브러리에 몇 가지 유형을 작성했습니다. 하지만 모든 상황에서 작동하는 솔루션은 없습니다.

솔루션 A

컨텍스트로 다시 동기화 할 필요가없는 간단한 비동기 메서드가있는 경우 Task.WaitAndUnwrapException 을 사용할 수 있습니다.

var task = MyAsyncMethod();
var result = task.WaitAndUnwrapException();

Task.Wait 또는 Task.Result AggregateException 에서 예외를 래핑하기 때문에 사용하지 않습니다 .

MyAsyncMethod 가 컨텍스트와 다시 동기화되지 않는 경우에만 적합합니다. 즉, MyAsyncMethod awaitConfigureAwait(false) 로 끝나야합니다. 즉, UI 요소를 업데이트하거나 ASP.NET 요청 컨텍스트에 액세스 할 수 없습니다.

솔루션 B

경우 MyAsyncMethod 문맥에 동기화 백업해야합니까, 당신은 사용할 수 있습니다 AsyncContext.RunTask 중첩 컨텍스트를 제공하기 위해 :

var result = AsyncContext.RunTask(MyAsyncMethod).Result;

* 2014 년 4 월 14 일 업데이트 : 최신 버전의 라이브러리에서 API는 다음과 같습니다.

var result = AsyncContext.Run(MyAsyncMethod);

(그것은 사용하기 괜찮습니다 Task.Result 하기 때문에이 예에서 RunTask 전파됩니다 Task 예외).

AsyncContext.RunTask 대신 Task.WaitAndUnwrapException 가 필요한 이유는 WinForms / WPF / SL / ASP.NET에서 발생하는 다소 미묘한 교착 상태 가능성 때문입니다.

  1. 동기식은 async 메소드를 호출하여 작업을 얻는다.
  2. 동기식 방법은 "Task"에서 차단 대기를 수행합니다.
  3. "async" 메소드는 "ConfigureAwait" 없이 "await"을 사용합니다.
  4. "Task"는 "async" 메소드가 완료되었을 때만 완료될 수 있으며, "async" 메소드는 "SyncContext" 및WinForms/WPF/SL/ASP에 대한 계속을 예약하려고 시도하고 있기 때문에 완료할 수 없습니다.동기식 메서드가 이미 해당 컨텍스트에서 실행 중이기 때문에 NET은 계속을 실행할 수 없습니다.

이것이 가능한 한 async 메서드 내에서 ConfigureAwait(false) 를 사용하는 것이 좋은 이유 중 하나입니다.

솔루션 C

AsyncContext.RunTask 는 모든 시나리오에서 작동하지 않습니다. 예를 들어 async 메서드가 UI 이벤트가 완료되어야하는 것을 기다리는 경우 중첩 된 컨텍스트에서도 교착 상태가됩니다. 이 경우 스레드 풀 async

var task = Task.Run(async () => await MyAsyncMethod());
var result = task.WaitAndUnwrapException();

그러나이 솔루션에는 스레드 풀 컨텍스트에서 작동 MyAsyncMethod 따라서 UI 요소를 업데이트하거나 ASP.NET 요청 컨텍스트에 액세스 할 수 없습니다. 이 경우 await ConfigureAwait(false) 를 추가하고 솔루션 A를 사용할 수 있습니다.

업데이트, 2019 년 5 월 1 일 : 현재 "최악의 방법"은 여기의 MSDN 문서에 있습니다 .

출처 : https://stackoverflow.com/questions/9343594/how-to-call-asynchronous-method-from-synchronous-method-in-c
728x90
반응형