You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 4.7.1中HttpClient.SendAsync遇HTTP 204触发空引用异常

.NET 4.7.1中HttpClient处理HTTP 204响应触发未捕获NullReferenceException的解决办法

问题详情

在目标框架为.NET 4.7.1的应用中,使用HttpClient执行GET请求时,若服务器返回HTTP 204(无内容)响应,会触发System.NullReferenceException,且该异常无法被try-catch语句捕获。相同请求在使用IHttpClientFactory的.NET Core应用中可正常运行。

涉及代码

protected async Task<HttpResponseMessage> GetResponse(string path, Dictionary<string, string> headers)
{
    HttpResponseMessage responseMessage = null;
    var request = new HttpRequestMessage(HttpMethod.Get, path);

    if (headers != null)
    {
        foreach (var header in headers)
        {
            request.Headers.Add(header.Key, header.Value);
        }
    }

    var proxy = new WebProxy
    {
        Address = new Uri($"http://{ProxyHost}:{ProxyPort}"),
        BypassProxyOnLocal = false,
        UseDefaultCredentials = false,
        Credentials = new NetworkCredential(userName: ProxyUser, password: ProxyPW)
    };

    // 创建使用该代理的客户端处理器
    var httpClientHandler = new HttpClientHandler
    {
        Proxy = proxy
    };

    var httpclient = new HttpClient(httpClientHandler);

    try
    {
        responseMessage = await httpclient.SendAsync(request);
    }
    catch (Exception ex)
    {
        // 错误处理逻辑
    }

    return responseMessage;
}

异常触发点

responseMessage = await httpclient.SendAsync(request);

Visual Studio捕获的未处理异常详情

System.NullReferenceException

  HResult=0x80004003

  Message=未将对象引用设置到对象的实例。

  Source=mscorlib

  StackTrace:

   at System.Threading.Tasks.AwaitTaskContinuation.RunCallback(ContextCallback callback, Object state, Task& currentTask)

--- End of stack trace from previous location ---

   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()

   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.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()

   at System.Threading.ThreadPoolWorkQueue.Dispatch()

 
  This exception was originally thrown at this call stack:

    [External Code]

事件查看器中的异常堆栈

StackTrace:    at System.Web.ThreadContext.AssociateWithCurrentThread(Boolean setImpersonationContext)

   at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext)

   at System.Web.LegacyAspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback callback, Object state)

   at System.Web.LegacyAspNetSynchronizationContext.CallCallback(SendOrPostCallback callback, Object state)

   at System.Threading.Tasks.AwaitTaskContinuation.RunCallback(ContextCallback callback, Object state, Task& currentTask)

--- End of stack trace from previous location where exception was thrown ---

   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()

   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.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()

   at System.Threading.ThreadPoolWorkQueue.Dispatch()

解决方案

该异常的根源并非HTTP 204响应本身,而是.NET Framework 4.7.1中旧ASP.NET同步上下文(LegacyAspNetSynchronizationContext)在异步回调时的空引用BUG,可通过以下方式解决:

1. 禁用旧ASP.NET同步上下文

在应用启动时(如Global.asax.cs的Application_Start方法)添加以下代码,强制使用新的同步上下文:

System.Web.AspNetSynchronizationContext.SetUseLegacyAspNetSynchronizationContext(false);

2. 优化HttpClient使用方式

  • 复用HttpClient实例:避免每次请求都创建新的HttpClient,复用实例能减少资源开销,同时规避部分同步上下文相关问题。
  • 指定响应完成选项:调用SendAsync时显式传入HttpCompletionOption.ResponseHeadersRead,确保即使是204响应也能正确返回响应对象:
responseMessage = await httpclient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);

3. 捕获未处理的异步任务异常

若禁用旧同步上下文不可行,可注册全局事件捕获未处理的异步任务异常,避免程序崩溃:

TaskScheduler.UnobservedTaskException += (sender, e) =>
{
    e.SetObserved();
    // 此处添加异常日志记录逻辑
};

4. 升级.NET Framework版本

如果条件允许,将应用升级到.NET Framework 4.8或更高版本,微软在后续版本中修复了多个异步同步上下文相关的BUG,可彻底解决此类问题。

内容的提问来源于stack exchange,提问作者redrobot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 21:20:59