【发布时间】:2014-04-16 23:24:17
【问题描述】:
我的程序出现了死锁,但我不知道为什么以及如何解决它。
短版:
async 到 sync 方法锁定等待异步调用,该调用调用另一个,依此类推,直到 HttpClient.PostAsync 调用。 http post 调用永远不会发生,至少它不会到达服务器(我也拥有它)。客户端没有错误。我的主要问题在这个 SO 问题的末尾。谢谢!
加长版:
我知道很容易出现死锁,我们必须小心。我正在尝试遵守以下建议:1. 将异步传播到所有方法和 2. 尽可能/有意义地使用 ConfigureAwait(false)。 (我认为这一点的主要倡导者是 Stephen Cleary 作为他的博客和许多我已经阅读过的许多 SO 的答案)。
嗯,我的程序...
不幸的是,我无法在此处发布完整的示例代码,它相当长;我将其描述为一个同步方法A,它调用一个异步方法B,它调用另一个异步,它调用另一个异步等。
最终最后一个异步调用是HttpClient.PostAsync。
程序在await HttpClient.PostAsync 停止。此外,Http 帖子永远不会触发(我拥有目标服务器,在这种情况下它永远不会收到请求)。 (我仔细检查了 uri 等)。
因此,同步方法锁定等待B 的异步任务完成,这永远不会发生。 A 看起来像这样:
public Byte[] A()
{
var task = BAsync();
return task.GetAwaiter().GetResult();
}
我以这种方式使用同步,因为他的方法不需要返回上下文,我看到 Nito 中 Stephen 建议的方法是使用 this 实现的。 (我也尝试了task.Result,但结果相同)。
http post调用的代码为:
private static async Task<HttpResponseMessage> PostAsync(Uri serverUri, HttpContent httpContent)
{
var client = new HttpClient();
return await client.PostAsync(serverUri, httpContent).ConfigureAwait(false);
}
应用的 UI 冻结。这是一个 WP8 应用程序。在这方面,按钮对Click 事件没有反应,但ScrollViews 仍然有效。这是另一个问题的主题,但我更喜欢在问题中包含这个细节。
我什至不确定我是否有死锁,或者可能是 HttpClient 错误? (我不这么认为,相同的方法在同一个应用程序的其他工作流程中起作用)。
我尝试验证死锁并使用 VS 的线程调试器窗口,但似乎只有主线程处于活动状态。我还尝试了所有其他类型的调试器窗口,但没有任何提示。
我的主要问题是:
- 我遇到了死锁吗?
- 如何验证(可能使用 VS)我确实有死锁?
- 是
Client.PostAsync吗?如果是,为什么以及如何解决? - 如果没有,请提供任何想法。
编辑:方法A 使用反射调用MethodInfo.Invoke。我相信现在这是问题的一部分。
【问题讨论】:
-
你能调用最后一个方法并验证它是否调用你的服务器吗?可能是由于一些愚蠢的错误,例如错误的 url 或参数
-
最后一种方法有效,我在应用程序的其他区域使用它没有问题。
标签: c# windows-phone-8 async-await dotnet-httpclient