Xamarin Forms中HttpClient请求极慢问题求助
解决三星设备上HttpClient请求缓慢/TaskCancelledException问题
看起来你遇到的问题在Xamarin.Android开发里并不少见,尤其是在部分三星设备上。结合你的代码和描述,我整理了几个关键的排查和修复方向:
1. 修复async void的问题
你在OnStart里调用的LoadFrom是async static void方法,这种写法只适合事件处理程序,在Android生命周期方法中使用会导致:
- 无法正确捕获异步操作的上下文,可能引发意外的任务取消
- 异常无法被上层try/catch捕获(除非借助SynchronizationContext)
修改方案:
- 把
LoadFrom改成async static Task - 在
OnStart里用await调用它(虽然OnStart是void,但这里用async void是生命周期方法的特例)
2. 复用HttpClient实例
你的代码每次调用LoadFrom都会新建一个HttpClient,频繁创建会耗尽系统的TCP连接池,直接导致请求变慢甚至失败。正确的做法是复用单例HttpClient。
3. 调整AndroidClientHandler的设置
部分三星设备对HTTP/2的支持有兼容性问题,禁用HTTP/2强制使用HTTP/1.1往往能解决慢请求的问题。同时设置合理的超时时间(30分钟太长了,5分钟足够测试)。
修改后的完整代码
public static class DataSource { // 全局复用HttpClient实例,避免频繁创建连接 private static readonly HttpClient _httpClient; static DataSource() { var handler = new Xamarin.Android.Net.AndroidClientHandler(); // 禁用HTTP/2,解决部分三星设备的兼容性问题 handler.DisableHttp2 = true; _httpClient = new HttpClient(handler); // 设置合理的超时时间 _httpClient.Timeout = TimeSpan.FromMinutes(5); } public async static Task LoadFrom() { var uri = new Uri("https://api.coinmarketcap.com/v2/ticker/?convert=usd&sort=price"); try { bool isConnected = CrossConnectivity.Current.IsConnected; if (!isConnected) { Debug.Print("No internet connection available"); return; } // 使用ConfigureAwait(false)避免捕获UI上下文,提升异步性能 var response = await _httpClient.GetAsync(uri).ConfigureAwait(false); // 直接抛出HTTP错误状态码,简化错误处理 response.EnsureSuccessStatusCode(); var data = await response.Content.ReadAsStringAsync().ConfigureAwait(false); var coinMarketCapObject = JsonConvert.DeserializeObject<CoinMarketCap.CoinMarketCapCurrencyData>(data); List<Currency> currencies = new List<Currency>(); if (coinMarketCapObject != null) { foreach (var datum in coinMarketCapObject.Data) { currencies.Add(new Currency(datum.Value.name, datum.Value.symbol, datum.Value.quotes.USD.price)); } } // 这里可以添加currencies的后续处理逻辑(比如通知UI更新) } catch (TimeoutException ex) { Debug.Print($"Request timed out: {ex.Message}"); } catch (TaskCanceledException ex) { // 区分手动取消和超时导致的任务取消 if (ex.CancellationToken.IsCancellationRequested) { Debug.Print("Request was cancelled manually"); } else { Debug.Print("Request timed out (TaskCanceledException)"); } } catch (Exception e) { Debug.Print($"Error loading data: {e.Message}"); } } }
修改OnStart方法:
protected override async void OnStart () { // Handle when your app starts await API.DataSource.LoadFrom(); }
额外排查方向
如果修改后问题依然存在,可以试试这些方法:
- 测试其他HTTPS接口(比如
https://jsonplaceholder.typicode.com/todos/1),确认是不是目标API本身的问题 - 检查三星设备的省电模式,部分省电策略会限制后台网络请求的速度
- 切换设备的DNS服务器(比如改成8.8.8.8),排查是不是DNS解析缓慢导致的问题
- 用抓包工具(比如Charles)分析请求流程,看是卡在DNS解析、TCP连接还是等待响应阶段
内容的提问来源于stack exchange,提问作者Amen Jlili
相关产品推荐
相关产品推荐

