[c#] HttpClient에서 await를 사용한 비동기 호출이 반환되지 않음

C#Win8 CP 의 xaml 기반 메트로 애플리케이션 내부에서 전화를 겁니다 . 이 호출은 단순히 웹 서비스에 도달하고 JSON 데이터를 반환합니다.

HttpMessageHandler handler = new HttpClientHandler();

HttpClient httpClient = new HttpClient(handler);
httpClient.BaseAddress = new Uri("http://192.168.1.101/api/");

var result = await httpClient.GetStreamAsync("weeklyplan");
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(WeeklyPlanData[]));
return (WeeklyPlanData[])ser.ReadObject(result);

멈춰 await있지만 http 호출은 실제로 거의 즉시 반환됩니다 (피들러를 통해 확인 됨). 마치 await무시되고 거기에 매달려 있습니다.

질문하기 전에 -예-사설 네트워크 기능이 켜져 있습니다.

왜 이것이 멈추는 지 아이디어가 있습니까?



답변

매우 유사한 내 질문에 대한 답변 을 확인하십시오 .

시도 할 방법 : ConfigureAwait(false)에서 반환 한 Task를 호출 합니다 GetStreamAsync(). 예

var result = await httpClient.GetStreamAsync("weeklyplan")
                             .ConfigureAwait(continueOnCapturedContext:false);

이것이 유용한 지 여부는 위의 코드가 어떻게 호출되는지에 따라 다릅니다. 제 경우에는을 async사용 하여 메서드를 호출 Task.GetAwaiter().GetResult()하면 코드가 중단됩니다.

이는 GetResult()Task가 완료 될 때까지 현재 스레드를 차단 하기 때문 입니다. 작업이 완료되면 시작된 스레드 컨텍스트를 다시 입력하려고 시도하지만 해당 컨텍스트에 이미 스레드가 있으므로 GetResult()교착 상태 에 대한 호출에 의해 차단됩니다 .

이 MSDN 게시물 은 .NET이 병렬 스레드를 동기화하는 방법에 대해 약간 자세히 설명 하며 내 질문에 대한 답변 은 몇 가지 모범 사례를 제공합니다.


답변

참고 사항-ASP.NET 컨트롤러의 최상위 수준에서 대기를 놓치고 응답으로 결과 대신 작업을 반환하면 실제로 중첩 된 대기 호출에서 오류없이 중단됩니다. 어리석은 실수이지만이 게시물을 봤다면 코드를 통해 이상한 것을 확인하는 데 시간을 절약 할 수 있었을 것입니다.


답변

면책 조항 : 저는 ConfigureAwait () 솔루션이 직관적이지 않고 기억하기 어렵 기 때문에 마음에 들지 않습니다. 대신 Task.Run (() => myAsyncMethodNotUsingAwait ())에서 대기하지 않은 메서드 호출을 래핑하는 결론에 도달했습니다. 이것은 100 % 작동하는 것처럼 보이지만 경쟁 조건 일 수 있습니다!? 솔직히 무슨 일이 일어나고 있는지 잘 모르겠습니다. 이 결론은 잘못되었을 수 있으며 주석에서 배우기 위해 StackOverflow 포인트를 위험에 빠뜨릴 수 있습니다. 읽어주세요!

방금 설명한대로 문제가 발생했으며 여기 에서 더 많은 정보를 찾았 습니다 .

문은 “비동기 메서드를 호출 할 수 없습니다”입니다.

await asyncmethod2()

차단하는 방법에서

myAsyncMethod().Result

제 경우에는 호출 방법을 변경할 수 없었고 비동기가 아닙니다. 하지만 실제로 결과에 대해서는 신경 쓰지 않았습니다. 내가 기억하기 때문에 .Result를 제거하고 await가 누락되었습니다.

그래서 이렇게했습니다.

public void Configure()
{
    var data = "my data";
    Task.Run(() => NotifyApi(data));
}

private async Task NotifyApi(bool data)
{
    var toSend = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
    await client.PostAsync("http://...", data);
}

제 경우에는 비동기 메서드 호출의 결과에 대해 신경 쓰지 않았지만이 사용 사례에서는 매우 일반적이라고 생각합니다. 호출하는 비동기 메서드에서 결과를 사용할 수 있습니다.


답변