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

如何修复C#中PostAsync请求未生效的代理配置问题?

问题描述

基于.NET Framework 4.6.1开发WPF的.dll组件,服务通过HTTP请求访问Azure Function服务器。已实现修改用户设置及配置代理的界面,但请求并未应用配置好的代理设置。

静态类ConnexionService代码

public static class ConnexionService
{
    private static HttpClient httpClient;
    private static HttpClientHandler clientHandler = new HttpClientHandler();

    public static void SetupProxy()
    {
        try
        {
            if (Properties.Settings.Default.ProxyUsage)
            {
                // 代理服务器地址和端口
                Uri proxyAddress = new Uri($"http://{Properties.Settings.Default.ProxyAdress}:{Properties.Settings.Default.ProxyPort}");

                // 创建代理对象
                WebProxy proxy = new WebProxy(Address: proxyAddress, BypassOnLocal: false)
                {
                    UseDefaultCredentials = false,
                    Credentials = new NetworkCredential(
                       userName: Properties.Settings.Default.ProxyUser,
                       password: Properties.Settings.Default.ProxyPassword)
                };
                
                // 创建HttpClientHandler并配置代理
                clientHandler = new HttpClientHandler()
                {
                    UseProxy = true,
                    Proxy = proxy
                };
                httpClient = new HttpClient(handler: clientHandler, disposeHandler: true);
            }
            else {
                httpClient = new HttpClient();
            }
        }
        catch(Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

    public static HttpClient getHttpClient()
    {
        SetupProxy();
        return httpClient;
    }
}

AuthenticationService中的使用代码

public class AuthenticationService 
{
    private readonly string Path = $"{Properties.Settings.Default.URL_API_DEV}/authentication";

    public async Task<Profile> LogIn(Profile profile)
    {
        var encryption = new Encryption();

        HttpContent content = new StringContent(encryption.Encrypt(JsonConvert.SerializeObject(profile)), Encoding.UTF8, "text/plain");
        try
        {
            using (var client = ConnexionService.getHttpClient())
            {
                var endpoint = new Uri($"{Path.Trim()}/login");

                var send = await client.PostAsync(endpoint, content);

                if (!send.IsSuccessStatusCode)
                {
                    Console.WriteLine($"错误 : {send.StatusCode}");
                    return new Profile();
                }

                var encryptedResult = await send.Content.ReadAsStringAsync();
                var decryptedResult = encryption.Decrypt(encryptedResult);
                var response = JsonConvert.DeserializeObject<Profile>(decryptedResult);
                return response;
            }
        }
        catch (HttpRequestException e)
        {
            Console.WriteLine($"错误 : {e.Message}");
            return new Profile();
        }
    }
}
问题分析与修复方案

核心问题

  1. 错误使用using销毁静态HttpClient:AuthenticationService中用using (var client = ConnexionService.getHttpClient())会自动销毁静态的httpClient实例,导致后续请求时实例已失效,代理配置无法生效,还会引发套接字资源耗尽问题。
  2. 重复创建HttpClient:getHttpClient()每次调用都会执行SetupProxy()重新创建HttpClient,违背了HttpClient设计为复用的原则,也会导致代理配置无法稳定生效。

修复步骤

  1. 移除using语句:静态HttpClient为长期复用设计,无需每次请求销毁,直接复用即可:

    // 替换原using块代码
    var client = ConnexionService.getHttpClient();
    var endpoint = new Uri($"{Path.Trim()}/login");
    var send = await client.PostAsync(endpoint, content);
    // 后续逻辑保持不变
    
  2. 优化ConnexionService逻辑:仅在代理配置变化时更新HttpClient实例,避免重复创建:

    public static class ConnexionService
    {
        private static HttpClient httpClient;
        private static HttpClientHandler clientHandler;
        // 记录当前代理配置,判断是否需要更新
        private static bool _currentProxyUsage;
        private static string _currentProxyAddress;
        private static int _currentProxyPort;
        private static string _currentProxyUser;
    
        public static void SetupProxy()
        {
            try
            {
                var settings = Properties.Settings.Default;
                // 配置无变化则直接返回
                if (httpClient != null 
                    && _currentProxyUsage == settings.ProxyUsage
                    && _currentProxyAddress == settings.ProxyAdress
                    && _currentProxyPort == settings.ProxyPort
                    && _currentProxyUser == settings.ProxyUser)
                {
                    return;
                }
    
                // 销毁旧实例
                httpClient?.Dispose();
                clientHandler?.Dispose();
    
                if (settings.ProxyUsage)
                {
                    Uri proxyAddress = new Uri($"http://{settings.ProxyAdress}:{settings.ProxyPort}");
                    WebProxy proxy = new WebProxy(proxyAddress, BypassOnLocal: false)
                    {
                        UseDefaultCredentials = false,
                        Credentials = new NetworkCredential(settings.ProxyUser, settings.ProxyPassword)
                    };
                    
                    clientHandler = new HttpClientHandler()
                    {
                        UseProxy = true,
                        Proxy = proxy
                    };
                    httpClient = new HttpClient(clientHandler, disposeHandler: true);
                    // 更新配置记录
                    _currentProxyUsage = true;
                    _currentProxyAddress = settings.ProxyAdress;
                    _currentProxyPort = settings.ProxyPort;
                    _currentProxyUser = settings.ProxyUser;
                }
                else 
                {
                    httpClient = new HttpClient();
                    // 更新配置记录
                    _currentProxyUsage = false;
                    _currentProxyAddress = null;
                    _currentProxyPort = 0;
                    _currentProxyUser = null;
                }
            }
            catch(Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    
        public static HttpClient getHttpClient()
        {
            SetupProxy();
            return httpClient;
        }
    }
    
  3. 监听配置变化:用户修改代理设置后,主动调用ConnexionService.SetupProxy()触发实例更新,确保新配置立即生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 05:55:32