c# - 将 HttpClient 设置为太短的超时会导致进程崩溃

标签 c# dotnet-httpclient

我注意到,当我使用 System.Net.HttpClient 时,超时时间很短,它有时可能会导致进程崩溃,即使它包含在 try-catch block 中也是如此。这是一个重现此内容的简短程序。

public static void Main(string[] args)
{
    var tasks = new List<Task>();
    for (int i = 0; i < 1000; i++)
    {
        tasks.Add(MakeHttpClientRequest());
    }
    Task.WaitAll(tasks.ToArray());

}

private async static Task MakeHttpClientRequest()
{            
    var httpClient = new HttpClient { Timeout = TimeSpan.FromMilliseconds(1) };
    var request = "whatever";
    try
    {
        HttpResponseMessage result =
            await httpClient.PostAsync("http://www.flickr.com/services/rest/?method=flickr.test.echo&format=json&api_key=766c0ac7802d55314fa980727f747710",
                                 new StringContent(request));             
        await result.Content.ReadAsStringAsync();                
    }
    catch (Exception x)
    {
        Console.WriteLine("Error occurred but it is swallowed: " + x);
    }
}

运行此命令将使进程崩溃,并出现以下异常:

Unhandled Exception: System.AggregateException: One or more errors occurred. ---> System.Net.WebException: The request was canceled
   at System.Net.ServicePointManager.FindServicePoint(Uri address, IWebProxy proxy, ProxyChain& chain, HttpAbortDelegate& abortDelegate, Int32& abortState)
   at System.Net.HttpWebRequest.FindServicePoint(Boolean forceFind)
   at System.Net.HttpWebRequest.get_ServicePoint()
   at System.Net.AuthenticationState.PrepareState(HttpWebRequest httpWebRequest)
   at System.Net.AuthenticationState.ClearSession(HttpWebRequest httpWebRequest)
   at System.Net.HttpWebRequest.ClearAuthenticatedConnectionResources()
   at System.Net.HttpWebRequest.Abort(Exception exception, Int32 abortState)
   at System.Net.HttpWebRequest.Abort()
   at System.Net.Http.HttpClientHandler.OnCancel(Object state)
   at System.Threading.CancellationCallbackInfo.ExecutionContextCallback(Object obj)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.CancellationCallbackInfo.ExecuteCallback()
   at System.Threading.CancellationTokenSource.CancellationCallbackCoreWork(CancellationCallbackCoreWorkArguments args)
   at System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(Boolean throwOnFirstException)
   --- End of inner exception stack trace ---
   at System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(Boolean throwOnFirstException)
   at System.Threading.CancellationTokenSource.NotifyCancellation(Boolean throwOnFirstException)
   at System.Threading.CancellationTokenSource.TimerCallbackLogic(Object obj)
   at System.Threading.TimerQueueTimer.CallCallbackInContext(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.TimerQueueTimer.CallCallback()
   at System.Threading.TimerQueueTimer.Fire()
   at System.Threading.TimerQueue.FireNextTimers()
   at System.Threading.TimerQueue.AppDomainTimerCallback()

稍微深入一点,似乎当 HttpClient 在创建相关的 ServicePoint 之前中止请求时,HttpWebRequest 会尝试创建 ServicePoint,通过 ServicePointManager.FindServicePoint,抛出 RequestCanceled。由于这个异常是在试图取消请求的线程中抛出的,它没有被捕获,进程就死掉了。

我错过了什么吗?你遇到过这个问题吗?

最佳答案

HttpWebRequest.Abort() 在后台/计时器线程上抛出异常。与HttpClient的Task管理无关。

HttpWebRequest.Abort() 的异常应该在 .NET 4.5 GDR1 中修复。 http://support.microsoft.com/kb/2750149 http://support.microsoft.com/kb/2750147

关于c# - 将 HttpClient 设置为太短的超时会导致进程崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15363536/

相关文章:

c# - 如何导航到同一解决方案中的另一个项目

c# - 如何定位具有最大圆环半径的圆环

c# - 配置命名 HttpClient 时是否可以在 Blazor WASM 中调用异步方法?

asp.net-core - 如何添加 Content-Type : application/octet-stream to .Net Core header

c# - Parallel.ForEach 与 HttpClient 和 ContinueWith

c# - 如何解决多个库中存在的 HttpClient

c# - 如何自动应用 generic.xaml 中的数据模板?

c# - 过滤以 `datagridview` 为界的 `datatable` 范围内的数据

c# - .NET HTTP 客户端。如何发布字符串值?

c# - ComboBoxCell 中的自定义绘制项