C#等待client.GetAsync()失败

时间:2014-06-08 11:55:07

标签: c# asynchronous amazon-web-services

我通过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";
}

2 个答案:

答案 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;
        ...

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