C# httpClient(异步调用块)死锁
C# httpClient (block for async call) deadlock
现状
有一个客户端通过 HttpClient.GetAsync 执行获取请求。不幸的是,出于某种原因,我们需要阻止该调用。
为此,使用此 Asynchelper class 以避免上下文切换死锁(而不是仅使用 .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.
不应该有一个异常会在连接丢失时结束这个调用吗?我错过了什么吗?
问题是 HTTP 连接通常通过 TCP 连接。因此,当您强行终止 TCP 连接而无法发送其 "I'm done here,"(或 FIN)数据包时,连接的另一端仍然乐于等待更多数据,至少直到某个定义的超时为止在套接字查询操作中从上面配置。
处理此问题的一种方法是在套接字上设置 TCP Keep-Alive。请注意,这与 HTTP Keep-Alive 有很大不同。另一种选择是,正如已经发生的那样,使用 good-enough 超时。
现状
有一个客户端通过 HttpClient.GetAsync 执行获取请求。不幸的是,出于某种原因,我们需要阻止该调用。
为此,使用此 Asynchelper class 以避免上下文切换死锁(而不是仅使用 .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.
不应该有一个异常会在连接丢失时结束这个调用吗?我错过了什么吗?
问题是 HTTP 连接通常通过 TCP 连接。因此,当您强行终止 TCP 连接而无法发送其 "I'm done here,"(或 FIN)数据包时,连接的另一端仍然乐于等待更多数据,至少直到某个定义的超时为止在套接字查询操作中从上面配置。
处理此问题的一种方法是在套接字上设置 TCP Keep-Alive。请注意,这与 HTTP Keep-Alive 有很大不同。另一种选择是,正如已经发生的那样,使用 good-enough 超时。