代理HttpHandler崩溃时异常捕获:如何重试或跳过失效代理
解决方案
问题分析
你的现有代码仅捕获了设置代理对象到HttpClientHandler这一步的异常,但实际代理失效的错误是在发送HTTP请求时抛出的,这部分逻辑未被包裹在异常捕获范围内,因此无法拦截目标错误。
修改方案
我们需要将HTTP请求逻辑纳入异常捕获范围,添加重试循环控制重试次数,捕获网络/代理相关的具体异常类型,最后在重试失败后跳过当前代理。
修改后的完整代码
private static async Task Check() { // 配置最大重试次数 const int maxRetryCount = 3; foreach (var cookieList in CookieList) { var user = JsonReader.readJSON("dataproxy.json", "proxyDetails", "proxyuser"); var pass = JsonReader.readJSON("dataproxy.json", "proxyDetails", "proxypass"); var proxyIp = JsonReader.readJSON("dataproxy.json", "proxyDetails", "proxyip"); var proxyPort = JsonReader.readJSON("dataproxy.json", "proxyDetails", "proxyport"); bool proxySuccess = false; int retryCount = 0; while (retryCount < maxRetryCount && !proxySuccess) { retryCount++; HttpClient client = null; try { var container = new CookieContainer(); var handler = new HttpClientHandler(); handler.CookieContainer = container; WebProxy proxy = new WebProxy(proxyIp, Convert.ToInt32(proxyPort)); if (user != null) { proxy.Credentials = new NetworkCredential(user, pass); } handler.Proxy = proxy; client = new HttpClient(handler); client.BaseAddress = BaseAddress; // 替换为你的实际请求逻辑,比如GetAsync/PostAsync var response = await client.GetAsync("your-target-api-path"); // 确保请求状态码正常,否则抛出HttpRequestException response.EnsureSuccessStatusCode(); proxySuccess = true; LogSystem.SendMessage($"代理 {proxyIp}:{proxyPort} 请求成功", Log.Type.Message); } // 捕获HttpClient请求异常(含代理连接失败、超时等) catch (HttpRequestException ex) { LogSystem.SendMessage($"代理 {proxyIp}:{proxyPort} 第{retryCount}次请求失败: {ex.Message}", Log.Type.Message); // 重试前添加短暂延迟,避免频繁请求 await Task.Delay(1000); } // 兼容旧版本的网络异常 catch (WebException ex) { LogSystem.SendMessage($"代理 {proxyIp}:{proxyPort} 第{retryCount}次请求失败(Web异常): {ex.Message}", Log.Type.Message); await Task.Delay(1000); } // 捕获底层连接异常 catch (SocketException ex) { LogSystem.SendMessage($"代理 {proxyIp}:{proxyPort} 第{retryCount}次请求失败(连接异常): {ex.Message}", Log.Type.Message); await Task.Delay(1000); } // 捕获其他意外异常,直接终止重试 catch (Exception ex) { LogSystem.SendMessage($"代理 {proxyIp}:{proxyPort} 发生未知错误: {ex.Message}", Log.Type.Message); break; } finally { // 释放HttpClient资源,避免内存泄漏 client?.Dispose(); } } if (!proxySuccess) { LogSystem.SendMessage($"代理 {proxyIp}:{proxyPort} 重试{maxRetryCount}次均失败,已跳过", Log.Type.Message); // 跳过当前代理,进入下一个循环 continue; } // 这里添加代理请求成功后的后续业务逻辑 } }
关键说明
- 重试控制:通过
maxRetryCount设定最大重试次数,用while循环实现重试逻辑 - 精准捕获:针对性捕获
HttpRequestException、WebException、SocketException,覆盖代理失效的常见场景 - 资源管理:在
finally块中释放HttpClient,避免资源泄漏 - 延迟重试:每次失败后延迟1秒,避免对目标服务或代理造成过大压力
- 跳过逻辑:重试全部失败后,用
continue跳过当前代理,继续处理下一个任务
内容的提问来源于stack exchange,提问作者Elie Meouchy
相关产品推荐
相关产品推荐

