Tenho uma chamada que estou fazendo de dentro de um C#
aplicativo metro baseado em xaml no Win8 CP; essa chamada simplesmente atinge um serviço da web e retorna dados 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);
Ele trava no, await
mas a chamada http na verdade retorna quase imediatamente (confirmado pelo fiddler); é como se o await
fosse ignorado e simplesmente permanecesse ali.
Antes de perguntar - SIM - o recurso de rede privada está ativado.
Alguma ideia de por que isso iria travar?
c#
asynchronous
async-await
dotnet-httpclient
keithwarren7
fonte
fonte
async
método? Não lança uma exceção?Respostas:
Verifique esta resposta à minha pergunta que parece ser muito semelhante.
Algo para tentar: chame
ConfigureAwait(false)
a Tarefa retornada porGetStreamAsync()
. Por exemploSe isso é útil ou não, depende de como o código acima está sendo chamado - no meu caso, chamar o
async
método usandoTask.GetAwaiter().GetResult()
fez com que o código travasse.Isso ocorre porque
GetResult()
bloqueia o thread atual até que a tarefa seja concluída. Quando a tarefa é concluída, ela tenta entrar novamente no contexto do encadeamento no qual foi iniciado, mas não consegue porque já existe um encadeamento nesse contexto, que está bloqueado pela chamada paraGetResult()
... deadlock!Esta postagem do MSDN apresenta alguns detalhes sobre como o .NET sincroniza threads paralelos - e a resposta dada à minha própria pergunta fornece algumas práticas recomendadas.
fonte
Apenas um aviso - se você perder o await no nível superior em um controlador ASP.NET e retornar a tarefa em vez do resultado como uma resposta, ele na verdade trava na (s) chamada (s) await aninhada (s) sem erros. Um erro bobo, mas se eu tivesse visto esta postagem, poderia ter me poupado algum tempo checando o código por algo estranho.
fonte
Isenção de responsabilidade: não gosto da solução ConfigureAwait () porque a considero não intuitiva e difícil de lembrar. Em vez disso, cheguei à conclusão de envolver chamadas de método não esperadas em Task.Run (() => myAsyncMethodNotUsingAwait ()). Isso parece funcionar 100%, mas pode ser apenas uma condição de corrida !? Não tenho certeza do que está acontecendo para ser honesto. Esta conclusão pode estar errada e arrisco meus pontos StackOverflow aqui para aprender com os comentários :-P. Por favor, leia-os!
Acabei de ter o problema conforme descrito e encontrei mais informações aqui .
A afirmação é: "você não pode chamar um método assíncrono"
de um método que bloqueia
No meu caso, não consegui alterar o método de chamada e não era assíncrono. Mas eu realmente não me importei com o resultado. Pelo que me lembro também não funcionou remover o .Result e ter o await faltando.
Então eu fiz isso:
No meu caso, não me importei com o resultado da chamada do método não assíncrono, mas acho que isso é bastante comum neste caso de uso. Você pode usar o resultado no método assíncrono de chamada.
fonte