HttpClient中带有wait的异步调用永远不会返回

本文关键字:永远 调用 返回 异步 wait HttpClient | 更新日期: 2023-09-27 18:29:06

我在Win8 CP上的一个基于xaml的C# metro应用程序内部进行了一个调用;这个调用只需点击一个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上,但http调用实际上几乎立即返回(通过fiddler确认);就好像CCD_ 3被忽略并且它只是挂在那里。

询问前-是-专用网络功能已打开。

你知道为什么会挂着吗?

HttpClient中带有wait的异步调用永远不会返回

看看我的问题的答案,它似乎非常相似。

尝试:对GetStreamAsync()返回的Task调用ConfigureAwait(false)。例如

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

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

这是因为GetResult()会阻塞当前线程,直到Task完成。当任务完成时,它会尝试重新进入启动它的线程上下文,但不能,因为该上下文中已经有一个线程,该线程被对GetResult()的调用阻止死锁

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

提醒一下-如果您错过了ASP.NET控制器中顶层的等待,并且返回了任务而不是结果作为响应,那么它实际上只是挂在嵌套的等待调用中,没有任何错误。这是一个愚蠢的错误,但如果我看到这篇文章,它可能会节省我一些时间来检查代码中是否有奇怪的东西。

免责声明:我不喜欢ConfigureAwait()解决方案,因为我觉得它不直观,很难记住。相反,我得出的结论是将未等待的方法调用包装在Task.Run(()=>myAsyncMethodNotUsingAwait())中。这似乎100%有效,但可能只是比赛条件!?老实说,我不太确定发生了什么。这个结论可能是错误的,我冒着StackOverflow的风险,希望能从评论中吸取教训:-P。请务必阅读!

我刚刚遇到了所描述的问题,并在这里找到了更多信息。

声明是:"你不能调用异步方法"

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

在我的例子中,我不关心调用非异步方法的结果,但我想这在这个用例中很常见。您可以在调用async方法中使用结果。