【问题标题】:HtttpClient async method throws TaskCanceledExceptionat first time executionHttpClient 异步方法在第一次执行时抛出 TaskCanceledException
【发布时间】:2015-12-07 23:03:16
【问题描述】:

我注意到HttpClientSendAsyncGetStringAsync 和其他 XxxAsync)的执行方法的一些奇怪行为。我已经使用这个类来登录多个服务器并执行它们的一些功能,我循环执行它并注意到在执行我的应用程序后它等待一段时间并报告第一台服务器失败,其他人很好,如果再试一次它报告成功。所以调试了这个方法并注意到在第一次执行HttpClient.SendAsync时它会抛出TaskCanceledException,实际上是TimeOutException,因为在HttpClient中没有人抛出那个异常(一定是微软设计的一些新的编码风格)。 所以我写了一些简单的例子:

public class MainClass
{
    public static void Main()
    {
        while (true)
        {
            foo();
            Console.ReadLine();
        }
    }
    static async void foo()
    {
        for (int i = 0; i < 10; i++)
        {
            Console.WriteLine((await Ping()).ToString());
        }
    }

    static async Task<bool> Ping()
    {
        bool result = false;
        try
        {
            var m_HttpHandler = new HttpClientHandler()
            {
                UseDefaultCredentials = true,
                UseCookies = false
            };
            HttpClient m_client = new HttpClient(m_HttpHandler);
            m_client.Timeout = new TimeSpan(0, 0, 4);

            var response = await m_client.GetStringAsync("http://google.com/");
            result = true;
        }
        catch (Exception ex) { Console.WriteLine(ex.ToString()); }
        return result;
    }
}

这给了我输出

System.Threading.Tasks.TaskCanceledException: Task canceled.
in System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
in System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
in System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
in MainClass.<LogOn>d__2.MoveNext() в C:\Users\HRR\Documents\Visual Studio 201
5\Projects\ConsoleApplication1\ConsoleApplication1\Program.cs: string 35
False
True
True
True
True
True
True
True
True
True

实际上它不会每次都抛出异常,有时不会,在某些 PC 上它工作正常(我已经在 win10 和 win8 机器上测试过,每次都运行良好),但在 Win7 上(经过测试在 2 台计算机上)它抛出异常...... 那么它有什么问题呢?

PS 在我的解决方案中,我有一些处理它的块。

更新 我已经尝试过默认的 100 秒,看起来它第一次连接大约 14 秒,接下来的连接花费的时间要少得多...

【问题讨论】:

  • 您的代码看起来不错。我唯一能看到的是您正在为请求设置超时,在某些情况下它很可能会超时。
  • 是的,但是我不明白怎么会只有第一次调用Ping()方法,为什么Win8/10的电脑上没有?
  • 里面有 InnerException 吗?
  • 当第一次连接需要很长时间时,是在服务器操作系统上吗?在客户端操作系统上也会发生同样的情况吗?
  • 不,没有内部异常。

标签: c# async-await httpclient


【解决方案1】:

我用m_client.Timeout = new TimeSpan(15) 试过了。这意味着 15 个滴答声的超时,显然在接收和应答之前超时。

有了这个超时,我也得到了你的TaskCanceledException所以看起来你的异常在请求超时时被抛出了。

我假设HttpClient.GetStringAsync 使用CancellationToken 启动一个任务,并且它会在超时后发出该令牌的信号。而内部任务抛出TaskCanceledException,因为它无法成功完成它的目的。

更新: 关于为什么有时在第一次尝试时有时会出现超时的问题:我没有太详细的知识,但据我所知,Windows 管理进程的带宽。您可以看到,如果您在网络中复制大文件:速度会缓慢增加,但是当您启动另一个需要网络的进程时,速度会迅速下降并在其他进程停止时再次缓慢恢复。因此,对于您在第一次尝试时超时并在以下请求中获得结果,我并不感到惊讶。

【讨论】:

  • 是的,在我的情况下 TaskCanceledException 是 TimeOutException,但我有疑问为什么它只是在第一次运行程序时抛出,在我的情况下,只是在 Win7 中,而不是在 Win10或 8 个;
  • 好吧,我不知道你的网络配置,但是超时 4 秒,一些客户端总是得到结果而其他客户端有问题也就不足为奇了。并且它在第一次尝试超时后起作用可以通过windows如何管理带宽来解释(我无法详细解释)。如果您想知道为什么您的客户端有不同的网络超时,这将是一个不同的问题。我试图在TaskCanceledException 上回答。
  • 其实我也试过 10 秒,连接那个时间太可笑了......但是我已经尝试了默认的 100 秒,它看起来第一次连接大约 14 秒,接下来的每个花费的时间要少得多......
  • 就像我说的 :) 但无法告诉您如何改善连接性。
猜你喜欢
  • 2023-01-12
  • 1970-01-01
  • 1970-01-01
  • 2017-06-03
  • 1970-01-01
  • 1970-01-01
  • 2011-08-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多