C# await client.GetAsync() failing
本文关键字:failing GetAsync await client | 更新日期: 2023-09-27 18:07:50
我通过HTTP从Amazon提取数据。代码在一个小的演示项目中工作得很好,但在我的主要应用程序中却不行。当我调用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";
}
我假设您在UI线程上调用此代码。正在发生的事情是,任务完成的Wait
导致死锁。您的FetchItem
方法是异步的,当您在其中使用await
时,下面的代码将转换为将在UI线程上执行的回调(称为continuation)。但是由于UI线程忙于等待任务完成,它无法处理回调,因此任务永远不会完成。因此出现了死锁。
永远不要对async方法的结果执行Wait
操作。如果调用异步方法,请使用await
来获取其结果。这意味着调用方法也必须是异步的。基本上,当你开始在代码的某些部分使用异步时,所有使用它的代码也需要变成异步的……(*)
(*)嗯,这并不完全正确。您可以通过在您的await
方法上调用ConfigureAwait(false)
来防止在UI线程上恢复异步方法。如果这样做,延续将在线程池线程上运行,而不是在UI线程上运行。这也将避免死锁。
我将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;
...
对我来说,重写一半的应用程序去异步是没有意义的。