2016-06-16 4 views
2

기본 저장소 클래스를 비동기로 만들려고하는데 문제가 있습니다. 내 C# 응용 프로그램에서 Dapper ORM을 사용하고 있습니다.async에서 기본 스레드를 차단/대기

자료 방법

protected async Task<List<T>> Read<T>(CommandDefinition cmd) { 
    using(SqlConnection myCon = new SqlConnection(Config.DBConnection)) { 
     await myCon.OpenAsync(); 

     IEnumerable<T> results = await myCon.QueryAsync<T>(cmd); 

     List<T> retVal = results.ToList(); 

     myCon.Close(); 

     return retVal; 
    } 
} 

방법 호출

public List<Category> GetAllActiveCategories(Guid siteGuid) { 
    return base.Read<Category>(SPNAME_GETALLACTIVE, siteGuid).Result; 
} 

모든 것이 나에게 위해를 찾습니다. async 키워드로 장식 된 메서드 선언이 있습니다. 비동기 메서드를 기다리고 있습니다.

내가 겪고있는 문제는 스레드가 await myCon.OpenAsync();에서 차단된다는 것입니다. 이것은 비동기 및 대기를 사용하는 첫 번째 시도이므로 잘못된 작업을 수행하고 있다고 확신하지만 분명하지는 않습니다. 도와주세요!

+0

@KirillShlenskiy 나는 당신이 뭔가있는 것 같아. 나는 그것을 사용하고있는 방법 중 하나를 보여주기 위해 대부분 편집 할 것입니다. – fizch

+0

이제는 소비 측면을 게시 했으므로 확신합니다. 내 의견을 답으로 다시 게시하십시오. –

답변

3

게시 된 읽기 코드가 정상입니다. 문제는 소비 코드에 있습니다. 호출 된 체인이 Task 인 경우 Wait() 또는 Result을 호출하거나 그 전제 인 Task을 호출하는 경우에는 async으로 교착 상태가되는 것이 일반적입니다.

언제나 그렇듯이 일반적인 조언이 적용됩니다 (don't block on async code). async/await을 사용하기 시작하면 전체 통화 체인에서 async/await을 사용해야합니다.

return base.Read<Category>(SPNAME_GETALLACTIVE, siteGuid).Result; 

는 키릴가 언급 한 바와 같이, 당신은 .Wait() 또는 .Result 사용하는 시간 :

그래서, 당신의 호출 방법은 범인이

public Task<List<Category>> GetAllActiveCategoriesAsync(Guid siteGuid) { 
    return base.Read<Category>(SPNAME_GETALLACTIVE, siteGuid); 
} 

... 또는

public async Task<List<Category>> GetAllActiveCategoriesAsync(Guid siteGuid) { 
    List<Category> result = await base.Read<Category>(SPNAME_GETALLACTIVE, siteGuid); 

    // Do something. 

    return result; 
} 
+0

내 유일한 질문은 어떻게됩니까? – fizch

+1

@fizch, 불행히도 async는 코드를 "중독시키는"방법을 가지고 있습니다. * 전체 * 체인을' 비동기'. 물론 동기식 호출 체인을 사용하는 경우 특정 상황에서 구식 차단 방법을 항상 사용할 수 있습니다. 대안으로'Read' 메쏘드에서 기다려온 모든'Task's에'ConfigureAwait (false)'를 사용하여 문제를 해결할 수 있습니다. 그러나 최선의 방법이지만'Task's를 의도적으로 차단하는 것은 여전히 반 패턴을 피해야합니다. –

+0

그러나 나는 더 이상 진술 된 원래의 질문에 대답하지 않으므로 빗 나간다. –

1

된다 작업에서 동기식으로 차단하고 있습니다.

public Task<List<Category>> GetAllActiveCategories(Guid siteGuid) { 
    return base.Read<Category>(SPNAME_GETALLACTIVE, siteGuid); 
} 

의 호출 방법이 방법에 작업을 반환, 등등 ... 그것은 "까지 모든 방법"비동기 수있다 : 당신이해야 할 것은 이것이다.

이 코드의 최상위 소비자가 ASP.NET이면 괜찮습니다. Task<IActionResult> (또는 Task에 포장 된 적절한 반환 유형)을 반환하면 프레임 워크가 await을 처리합니다.

당신이 콘솔 응용 프로그램을 작성하는 경우 또는 기타는 "까지 모든 방법 비동기"당신이 .Result에 블록 하나에이 있거나 방법 async void을하고 await를 사용합니다 할 수 없습니다. 어느 쪽도 슬프게도 훌륭한 해결책이 아닙니다. Async/await은 스택 전체에서 사용해야한다는 의미에서 꽤 공격적입니다.

+0

@fizch 약간의 설명을 추가했습니다. Kirill의 답변 (및 링크)도 좋은 정보입니다! –

관련 문제