C#中不await HttpClient.PostAsync请求不触发的原因及无等待方案
问题原因解析
无async/await的Task返回方法请求未触发的原因
- 你写的不带
async关键字的SubmitMetric方法中,httpClient.PostAsync仅会返回一个未完成的Task对象,此时HTTP请求还没走完发送流程,方法就直接退出了using代码块,HttpClient会被立即执行Dispose释放 - 还在执行中的异步请求被提前释放的HttpClient直接中止,所以请求根本没有成功发出去
- 加上
async/await之后,方法会在PostAsync处暂停执行,直到请求发送的异步操作完成(至少是完成请求数据写入网络流的阶段),才会继续执行后续的using块结束逻辑、释放HttpClient,因此请求可以正常提交
无返回值的fire-and-forget写法是否可行
你给出的
void SubmitMetric写法完全不可行,存在以下问题:
- 和第一个写法的核心问题完全一致:
PostAsync调用后还没来得及发送请求,HttpClient就被using释放,请求会被直接中止 - 没有被await的
Task如果后续抛出异常(比如网络不通、请求超时),会产生未观察到的Task异常,虽然.NET Core 2.1+之后这类异常默认不会终止进程,但依然会占用系统日志资源,也可能隐藏业务故障
发完请求就不管的正确实现方案
- 首先不要每次调用都手动new
HttpClient,推荐直接注入.NET框架提供的IHttpClientFactory来创建HttpClient,无需手动管理释放,也能避免频繁创建HttpClient导致的端口耗尽问题 - 确实需要fire-and-forget逻辑的话可以按以下方式实现,同时增加异常处理避免未观察异常:
// 服务类中先注入IHttpClientFactory private readonly IHttpClientFactory _httpClientFactory; public YourService(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; } public void SubmitMetric(<params>) { // 构造请求 payload var httpClient = _httpClientFactory.CreateClient(); // 丢弃Task的同时追加异常处理逻辑 _ = httpClient.PostAsync(<params>) .ContinueWith(t => { if (t.IsFaulted) { // 此处写入异常日志记录逻辑即可,不要向外抛异常 Console.WriteLine(t.Exception?.ToString()); } }, TaskContinuationOptions.OnlyOnFaulted); }
内容的提问来源于stack exchange,提问作者Muhammad Jabareen
相关产品推荐
相关产品推荐

