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

C# await client.GetAsync() failing

我假设您在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;
        ...

对我来说,重写一半的应用程序去异步是没有意义的。