Task 결과에 접근할 때 C# 비동기 메서드가 중단되는 이유
비동기 프로그래밍에 C#의 async
및 await
키워드를 사용할 때 특정 구문으로 인해 예기치 않은 동작과 잠재적인 교착 상태가 발생할 수 있습니다.
다음 시나리오를 고려해 보세요. 다중 계층 애플리케이션은 SQL 쿼리를 비동기적으로 실행하고 결과를 반환하는 확장된 데이터베이스 유틸리티 메서드ExecuteAsync
를 사용합니다. 중간 계층 메서드 GetTotalAsync
는 ExecuteAsync
을 호출하여 데이터를 검색하고 결과를 asyncTask
변수에 저장합니다. 마지막으로 UI 작업은 asyncTask.Result
을 사용하여 동기적으로 결과에 액세스하려고 시도합니다. 그러나 응용 프로그램이 무기한 중단됩니다.
교착상태의 원인
GetTotalAsync
메서드에 await
을 사용하면 문제가 발생합니다. 기본적으로 비동기 메서드의 연속은 해당 메서드를 시작한 동일한 SynchronizationContext
에서 전달됩니다. 이 경우 UI 스레드에서 await
을 사용하면 연속(return result;
)도 UI 스레드에서 실행되도록 예약됩니다.
UI 스레드에서 asyncTask.Result
을 호출하면 작업이 완료될 때 스레드가 차단됩니다. 그러나 UI 스레드에 예약된 연속 작업은 asyncTask.Result
이 완료될 때까지 실행할 수 없습니다. 이로 인해 두 스레드 모두 실행을 계속할 수 없는 교착 상태가 발생합니다.
솔루션
이 교착상태를 해결하기 위해서는 여러 가지 방법이 있습니다:
1. 비동기 키워드 삭제:
await
사용을 제거하고 ExecuteAsync
및 GetTotalAsync
메서드를 기다리지 않는 순수 비동기 메서드로 다시 작성합니다.
<code class="language-csharp">public static Task<T> ExecuteAsync<T>(this OurDBConn dataSource, Func<OurDBConn, T> function) { // ... (代码保持不变) } public static Task<ResultClass> GetTotalAsync(...) { // ... (代码保持不变) }</code>
2. ConfigureAwait 사용:
UI 스레드에서 연속 작업을 예약하지 않도록 지정하려면 ConfigureAwait(false)
을 사용하세요.
<code class="language-csharp">public static async Task<ResultClass> GetTotalAsync(...) { var resultTask = this.DBConnection.ExecuteAsync<ResultClass>( ds => ds.Execute("select slow running data into result")); return await resultTask.ConfigureAwait(false); }</code>
이 접근 방식을 사용하려면 교착 상태로 이어질 수 있는 모든 await
작업에 대해 ConfigureAwait(false)
을 명시적으로 지정해야 합니다.
3. 동기화 컨텍스트 사용:
비동기 작업을 위한 특정 SynchronizationContext
을 만들고 모든 await
작업이 해당 컨텍스트를 사용하는지 확인하여 UI 스레드와의 충돌을 방지합니다.
위 내용은 작업 결과에 액세스할 때 비동기 C# 메서드가 중단되는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!