c# webclient 和 httpclient 的区别

来源:这里教程网 时间:2026-02-21 17:38:16 作者:

WebClient 一调就报 WebException,HttpClient 却不抛异常?

这是最常踩的坑:用

WebClient
请求一个返回 404 或 500 的 API,代码直接崩在
DownloadString
上,抛出
WebException
;而换成
HttpClient
GetAsync
照常返回
HttpResponseMessage
,得手动检查
response.IsSuccessStatusCode
才知道失败了。

WebClient
把所有非 2xx 状态码当“异常”处理(哪怕 404 是你预期的业务结果)
HttpClient
只在真正出问题时才抛
HttpRequestException
(比如 DNS 失败、连接超时、服务器完全不可达)
这意味着:用
WebClient
你得 try-catch 每次调用;用
HttpClient
你可以统一判断
StatusCode
,再分情况处理(如 401 跳登录、404 提示资源不存在)

为什么 new HttpClient() 用几次就卡死或报 SocketException?

这不是 bug,是误用。很多人照着示例写

using (var client = new HttpClient())
,结果高并发下出现
SocketException: Only one usage of each socket address is normally permitted

HttpClient
设计为**长生命周期复用**,不是一次性的 —— 它背后维护 TCP 连接池
每次
new HttpClient()
都新建连接池,频繁创建销毁会快速耗尽本地端口(TIME_WAIT 状态堆积)
WebClient
虽也有类似风险,但因默认同步+低并发场景多,问题不明显;而
HttpClient
异步高频使用时立刻暴露
正确做法:全局单例、DI 注入
IHttpClientFactory
,或至少在类级别复用实例

上传文件、下载大文件,该选哪个?

看需求粒度。如果只是“把本地文件发到某个 URL”,

WebClient.UploadFile
一行搞定;但如果要监控进度、设超时、加 token、支持断点续传、或上传流式数据(比如压缩中上传),
HttpClient
是唯一选择。

WebClient
:只支持完整文件路径上传,不支持
Stream
或分块;无进度回调;不能设
Timeout
(只能靠底层
WebRequest
默认值)
HttpClient
:可传
StreamContent
、设
client.Timeout = TimeSpan.FromSeconds(60)
、用
Progress<httpprogress></httpprogress>
监听上传进度、支持
CancelToken
中断
注意:
WebClient
UploadFileAsync
声称异步,但底层仍是同步 I/O 封装,无法真正释放线程;
HttpClient
的异步才是真正的 awaitable I/O

新项目里还能用 WebClient 吗?

能,但不建议。.NET 官方已将

WebClient
标记为 [Obsolete](https://learn.microsoft.com/en-us/dotnet/api/system.net.webclient?view=net-8.0#remarks)(自 .NET 6 起警告,.NET 8+ 默认启用警告)。

它不支持 HTTP/2、不支持请求拦截器、不能配置消息处理器链(比如自动加 Auth Header)、无法集成 Polly 重试 所有现代库(如 Refit、Flurl)都基于
HttpClient
构建;第三方认证库(Microsoft.Identity.Web)也只提供
HttpClient
扩展
例外场景:写个临时控制台工具快速抓网页内容,
new WebClient().DownloadString(url)
确实快——但这种“快”是以牺牲可维护性和未来扩展性换来的

真正容易被忽略的点是:异常语义差异不是风格偏好,而是设计契约。把 404 当异常捕获,等于把“资源不存在”当成程序错误;而把它作为正常响应处理,才能写出可预测、可观测、易测试的 HTTP 客户端逻辑。

相关推荐