簡體   English   中英

HttpClient 在 GetAsync 上使用 await 時不會拋出異常

[英]HttpClient not throwing exception when using await on GetAsync

我正在使用以下代碼獲取端點並將其寫入緩存:

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 中運行的代碼有關,但為什么呢? 如何在不需要開始新任務的情況下正確拋出異常?

我的直覺告訴我,你正在調用WaitResult進一步調用你的調用堆棧。

如果這是正確的,那么您將導致僵局,正如我在我的博客中所解釋的那樣。

由於我遇到了沒有拋出異常的相同行為,我創建了一個示例來演示該問題的可能解決方案:

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。 希望,它可以幫助任何人:-)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM