我通过HTTP从亚马逊提取数据。代码在一个小型演示项目中运行得很好,但在我的主应用程序中它并没有。当我拨打FetchItem()
时,我会收到此输出:
'System.Net.Http.Formatting.dll'. Cannot find or open the PDB file.
等待client.GetAsync()
后,函数返回,url.Wait()
永远等待。
用法
Task<string> url = FetchItem("ItemName", requestUrl);
url.Wait();
return url.Result;
FetchItem的来源
private static async Task<string> FetchItem(string sItemName, string url)
{
try
{
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
XElement content = await response.Content.ReadAsAsync<XElement>();
XNamespace ns = NAMESPACE;
var isValidResults = content.Descendants(ns + "IsValid").AsParallel();
foreach (var item in isValidResults)
{
if (item.Value != "True")
return "Invalid Request";
}
var titleResults = content.Descendants(ns + sItemName).AsParallel();
foreach (var item in titleResults)
{
if (item.Name == ns + sItemName)
return item.Value;
// depending on the keyword, results can be quite fun.... :-)
}
}
catch (Exception e)
{
System.Console.WriteLine("Caught Exception: " + e.Message);
System.Console.WriteLine("Stack Trace: " + e.StackTrace);
}
return "Error";
}
答案 0 :(得分:3)
我假设您在UI线程上调用此代码。发生的事情是Wait
完成任务导致死锁。您的FetchItem
方法是异步的,当您在其中使用await
时,后面的代码将转换为将在UI线程上执行的回调(称为延续)。但由于UI线程忙于等待任务完成,因此无法处理回调,因此任务永远不会完成。因此陷入僵局。
对于异步方法的结果,您永远不应该Wait
。如果您调用异步方法,请使用await
获取其结果。这意味着调用方法也必须是异步的。基本上,当你开始在代码的某些部分使用异步时,使用它的所有代码也需要变得异步......(*)
(*)嗯,这不完全正确。您可以通过在ConfigureAwait(false)
方法上调用await
来阻止异步方法在UI线程上恢复。如果这样做,延续将在线程池线程上运行,而不是在UI线程上运行。这也可以避免僵局。
答案 1 :(得分:0)
我更改了FetchItem()
以运行同步。这样做对我来说:
private static string GetItem(string sItemName, string url)
{
try
{
HttpClient client = new HttpClient();
HttpResponseMessage response = client.GetAsync(url).Result;
response.EnsureSuccessStatusCode();
XElement content = response.Content.ReadAsAsync<XElement>().Result;
...
将我的应用程序的一半重写为异步对我来说没有意义。