C#httpClient(用于异步调用的块)死锁

时间:2016-01-28 16:26:12

标签: c# async-await dotnet-httpclient contextswitchdeadlock

现状

有一个客户端通过HttpClient.GetAsync执行get请求。不幸的是,出于某种原因,我们需要阻止这些电话。

为了做到这一点,使用这个Asynchelper类是为了避免上下文切换死锁(而不仅仅是使用.Result)

   public static class AsyncHelper
   {
       private static readonly TaskFactory _myTaskFactory = new
             TaskFactory(CancellationToken.None,
                         TaskCreationOptions.None,
                         TaskContinuationOptions.None,
                         TaskScheduler.Default);


    public static void RunSync(Func<Task> func)
    {
        AsyncHelper._myTaskFactory
          .StartNew<Task>(func)
          .Unwrap()
          .GetAwaiter()
          .GetResult();
    }
}

然后实际调用如下:

AsyncHelper.RunSync(Async Function() Await _httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead))

问题

在使用Netlimiter降低网络速度的压力测试期间,我们遇到了未完成的请求的问题。 例如,当我终止网络连接时(在NetLimiter中),这样的请求将永远留在客户端。 它将保留在AsyncHelper.RunSync调用中,直到它进入httpClient.Timeout。

当连接丢失时,是否会有异常终止此呼叫?我错过了什么吗?

1 个答案:

答案 0 :(得分:3)

问题是HTTP连接通常通过TCP连接。因此,当您强行终止TCP连接而无法发送其“我在这里完成”(或FIN)数据包时,连接的另一端仍然乐于等待更多数据,至少在某些已定义的超时之前可以在套接字查询操作中从上面配置。

处理此问题的一种方法是在套接字上设置 TCP Keep-Alive 。请注意,这与 HTTP Keep-Alive非常不同。另一种选择是,似乎已经发生了使用足够好的超时。