我正在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
但 http 调用几乎立即返回(通过fiddler确认);好像await
被忽略了,只是挂在那里。
在您提出之前 - 是 - 已打开专用网络功能。
为什么会挂起来的任何想法?
答案 0 :(得分:118)
查看this answer我的问题,看似非常相似。
要尝试的内容:在ConfigureAwait(false)
返回的任务上调用GetStreamAsync()
。 E.g。
var result = await httpClient.GetStreamAsync("weeklyplan")
.ConfigureAwait(continueOnCapturedContext:false);
这是否有用取决于上面代码的调用方式 - 在我的情况下使用async
调用Task.GetAwaiter().GetResult()
方法导致代码挂起。
这是因为GetResult()
阻止当前线程,直到任务完成。当任务完成时,它会尝试重新进入启动它的线程上下文但不能,因为在该上下文中已经存在一个线程,该线程被GetResult()
的调用阻止... 死锁!强>
This MSDN post详细介绍了.NET如何同步并行线程 - the answer given to my own question提供了一些最佳实践。
答案 1 :(得分:1)
请注意-如果您错过了ASP.NET控制器顶层的等待,并且返回了任务而不是结果作为响应,则它实际上只是挂在嵌套的等待调用中,没有错误。一个愚蠢的错误,但是如果我看过这篇文章,它可能节省了我一些时间来检查代码中是否有奇怪的事情。
答案 2 :(得分:0)
免责声明:我不喜欢ConfigureAwait()解决方案,因为我发现它不直观且难以记住。相反,我得出结论,将未等待的方法调用包装在Task.Run(()=> myAsyncMethodNotUsingAwait())中。这似乎可以100%起作用,但可能只是比赛条件!?我不太确定这是怎么回事。这个结论可能是错误的,我冒着我在此处的StackOverflow风险,希望从评论中学习:-P。请务必阅读它们!
我只是遇到了上述问题,并找到了更多信息here。
该语句是:“您不能调用异步方法”
await asyncmethod2()
通过阻止的方法
myAsyncMethod().Result
就我而言,我无法更改调用方法,并且它不是异步的。但是我实际上并不关心结果。我记得它也无法删除.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);
}
就我而言,我并不在乎调用非异步方法的结果,但我想在这种用例中这很普遍。您可以在调用异步方法中使用结果。