HttpClient 中带等待的异步调用永远不会返回

我在 Win8 CP 上的一个基于 xaml 的 C#都市应用程序内部进行了一次调用; 这次调用只是简单地命中一个 Web 服务并返回 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上,但是 译注:调用实际上几乎立即返回(通过 fiddler 确认) ; 就好像 await被忽略了,它只是挂在那里。

在你问之前 -YES-专用网络功能已经打开。

知道为什么这个会挂起来吗?

77453 次浏览

看看 这个答案对我的问题,似乎是非常相似的。

尝试一下: 对 GetStreamAsync()返回的任务调用 ConfigureAwait(false)

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

这是否有用取决于如何调用上面的代码-在我的例子中,使用 Task.GetAwaiter().GetResult()调用 async方法导致代码挂起。

这是因为 GetResult()在 Task 完成之前阻塞当前线程。当任务完成时,它尝试重新进入启动它的线程上下文,但是不能,因为在那个上下文中已经有一个线程,这个线程被对 GetResult()... 僵局!的调用阻塞

这篇 MSDN 文章 详细介绍了如何。NET 同步并行线程-我自己问题的答案给出了一些最佳实践。

免责声明: 我不喜欢 ConfigureAwait ()解决方案,因为我觉得它不直观,很难记住。相反,我得出的结论是在 Task 中包装非等待方法调用。运行(() = > myAsyncMethodNotUsingAwait ())。这似乎工作100% ,但可能只是一个比赛条件! ?我不确定到底发生了什么。这个结论可能是错误的,我冒险在这里提出我的 StackOverflow 观点,希望能从评论中学到一些东西。请一定要读!

我只是有问题的描述和发现更多的信息 给你

The statement is: "you can't call an asynchronous method"

await asyncmethod2()

从阻塞

myAsyncMethod().Result

在我的例子中,我不能更改调用方法,而且它不是异步的。但我并不在乎结果如何。我记得它也没有工作,删除。结果和等待失踪。

所以我这么做了:

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);
}

在我的例子中,我并不关心调用非异步方法的结果,但是我猜想这在这个用例中是相当常见的。可以在调用异步方法中使用结果。

Just a heads up - if you miss the await at the top level in an ASP.NET controller, and you return the task instead of the result as a response, it actually just hangs in the nested await call(s) with no errors. A silly mistake, but had I seen this post it might have saved me some time checking through the code for something odd.