5

我正在使用以下代码获取端点并将其写入缓存:

public async Task UpdateCacheFromHttp(string Uri)
{
    if (string.IsNullOrEmpty(Uri))
        return;

    var httpClient = new HttpClient();
    var response = await httpClient.GetAsync(Uri);

    if ((response != null) && (response.IsSuccessStatusCode))
    {
        var responseStream = await response.Content.ReadAsStreamAsync();
        WriteToCache(responseStream);
    }
}

代码在 IIS 上运行。

如果无法到达端点,我希望 GetAsync 会引发异常。即使使用 Try-Catch,它似乎也永远不会失败。GetAsync 永远不会返回(我在 HttpClient 上尝试了 5 秒超时,但仍然没有返回)。

这确实会引发异常:

public Task UpdateCacheFromHttp(string Uri)
{
    var updateCacheTask = Task.Factory.StartNew(new Action(() =>
    {
        if (string.IsNullOrEmpty(Uri))
            return;

        var httpClient = new HttpClient();
        var response = httpClient.GetAsync(Uri).Result;

        if (response.IsSuccessStatusCode)
        {
            var responseStream = response.Content.ReadAsStreamAsync().Result;
            WriteToCache(responseStream);
        }
    }));

    return updateCacheTask;
}

我得到预期的“无法连接到远程服务器”。

我怀疑它与在 IIS 中运行的代码有关,但为什么呢?如何让它正确抛出异常而无需开始新任务?

4

2 回答 2

18

我的直觉告诉我,您正在调用WaitResult进一步调用您的调用堆栈。

如果这是正确的,那么正如我在我的博客中解释的那样,您正在造成死锁。

于 2013-04-08T17:49:14.450 回答
-1

当我遇到相同的行为而没有抛出异常时,我创建了一个示例来演示可能的解决方案的问题:

using System;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;

namespace Exam
{
    public static class Program
    {
        private static async Task<string> GetWebPage(string uri)
        {
            var httpClient = new HttpClient();
            var response = await httpClient.GetAsync(new Uri(uri, UriKind.Absolute), HttpCompletionOption.ResponseContentRead);
            return await response.Content.ReadAsStringAsync();
        }

        public static void Main(string[] args)
        {
            try
            {
                // These two lines do not work - i.e. it terminates the application without any exception being thrown...
                //string s = await GetWebPage(@"https://www.dwd.de/DE/leistungen/klimadatendeutschland/klimadatendeutschland.html");
                //Console.WriteLine(s);

                // This works:
                Task<string> getPageTask = GetWebPage(@"https://www.dwd.de/DE/leistungen/klimadatendeutschland/klimadatendeutschland.html");
                getPageTask.Wait();
                if (getPageTask.IsCompleted)
                    Console.WriteLine(getPageTask.Result);
            }
            catch (AggregateException aex)
            {
                aex.InnerExceptions.AsParallel().ForAll(ex => Console.WriteLine(ex));
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            Console.ReadKey();
        }
    }
}

当您另外将 URI 更改为 @"invalid https://...." 之类的内容时,您将检索 AggregateException。希望,它可以帮助任何人:-)

于 2021-01-01T18:11:33.657 回答