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

ASP.NET MVC中WebClient.UploadString抛出ThreadAbortException原因排查

问题

生产环境中,我们的ASP.NET MVC(.NET Framework 4.8)应用使用WebClient.UploadString向同机器另一IIS站点的自有API发送HTTP POST请求,payload大小正常,但接收API有时处理耗时较长,偶尔会抛出以下异常:

System.Threading.ThreadAbortException: Thread was being aborted.
   at System.Net.UnsafeNclNativeMethods.OSSOCK.recv(IntPtr socketHandle, Byte* pinnedBuffer, Int32 len, SocketFlags socketFlags)
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, SocketError& errorCode)
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead)
   at System.Net.ConnectStream.ProcessWriteCallDone(ConnectionReturnResult returnResult)
   at System.Net.HttpWebRequest.CheckDeferredCallDone(ConnectStream stream)
   at System.Net.HttpWebRequest.GetResponse()
   at System.Net.WebClient.GetWebResponse(WebRequest request)
   at System.Net.WebClient.DownloadBits(WebRequest request, Stream writeStream, CompletionDelegate completionDelegate, AsyncOperation asyncOp)
   at System.Net.WebClient.UploadDataInternal(Uri address, String method, Byte[] data, WebRequest& request)
   at System.Net.WebClient.UploadString(Uri address, String method, String data)
   at System.Net.WebClient.UploadString(String address, String method, String data)

查看.NET WebClient源码可知,它有时会捕获并重新抛出ThreadAbortException(符合预期行为),但我们无法复现该异常的触发原因。

我们尝试了以下场景测试,均出现错误但未触发ThreadAbortException:

  • 用无限Thread.Sleep模拟API长时间运行,MVC站点最终超时而非抛出异常;
  • 请求API60秒后终止API应用,仅得到远程服务器错误;
  • MVC应用独立运行,API部署在IIS,请求时终止IIS,同样仅得到远程服务器错误。

请问从上述堆栈跟踪来看,什么情况会触发ThreadAbortException?该异常似乎来自OSSOCK.recv,具体原因是什么?

分析与解答

从堆栈轨迹和ThreadAbortException的特性(仅由线程被外部强制终止触发)来看,触发该异常的核心原因是执行WebClient.UploadString的本地线程被强制终止,而非远程API的直接错误,具体场景如下:

1. ASP.NET请求线程因超时被回收

ASP.NET运行时会监控请求的执行时长:

  • 如果你的MVC请求(包含等待API响应的时间)超过了web.config中httpRuntime节点的executionTimeout配置值(默认110秒),ASP.NET会调用Thread.Abort()强制终止当前请求线程。此时线程正阻塞在底层socket的recv调用(等待API响应数据)阶段,就会抛出这个异常。
  • 这和你测试的API超时场景本质不同:API超时是WebClient自身的超时逻辑触发(默认100秒),会抛出WebException;而ASP.NET的线程回收是外部强制终止线程,直接抛出ThreadAbortException。

2. MVC应用所在的应用池被回收

当MVC应用的IIS应用池触发回收(比如定时回收、内存阈值触发回收、手动回收),或者进程被强制终止时:

  • 如果回收动作发生在WebClient.UploadString的阻塞IO阶段,CLR会终止当前正在执行的线程,从而触发ThreadAbortException。
  • 你测试的终止API/IIS场景属于远程连接中断,会触发正常的网络错误;而应用池回收是本地线程被强制终止,两者触发的异常类型完全不同。

3. 底层Socket操作被系统级操作中断

某些系统级别的操作可能直接中断socket的recv调用:

  • 比如Windows TCP/IP栈重置、网络适配器重启,或者杀毒软件/防火墙强制中断了本地socket连接,导致线程在等待响应数据时被强制终止。
  • 这种情况相对少见,但会直接在OSSOCK.recv层面触发线程中止异常。

测试场景与生产场景的核心差异

你做的测试都是针对API端的异常,而生产中触发ThreadAbortException的关键是本地线程被强制终止:

  • 测试时MVC请求本身未达到超时阈值,也未触发应用池回收,因此只会触发远程API相关的错误;
  • 生产中则是MVC请求因等待API响应时间过长,导致整体请求超时被ASP.NET回收,或者应用池刚好在请求执行过程中触发回收。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 20:09:55