为什么这个HttpClient用法给了我"无法访问已处置的对象".错误?

jam*_*mie 18 c# httpclient

我已经简化了一些代码,但基本上这一直给我一个"无法访问已处置的对象".错误,我无法解决原因?

我有多个同时运行的任务执行GET,然后解析一些HTML,然后根据GET的结果执行POST.

这段代码所在的方法返回一个带有结果的事件对象,所以我认为我不能使用await,因为该方法需要返回void?

foreach (Account accountToCheck in eventToCheck.accountsToRunOn)
{
    Task.Run(() =>
    {
        HttpClientHandler handler = new HttpClientHandler();
        CookieContainer cookies = new CookieContainer();
        handler.CookieContainer = cookies;
        using (var client = new HttpClient(handler))
        {
            ServicePointManager.ServerCertificateValidationCallback = delegate (object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };
            client.Timeout = new TimeSpan(0, 0, 3);
            client.DefaultRequestHeaders.Add("Keep-Alive", "false");
            HttpResponseMessage response = client.GetAsync("https://test.com", HttpCompletionOption.ResponseContentRead).Result;
            string html = response.Content.ReadAsStringAsync().Result;

            var content = new FormUrlEncodedContent(new[]
            {
                new KeyValuePair<string, string>("test[username_or_email]",  accountToLogIn.accountHandle),
                new KeyValuePair<string, string>("test[password]",           accountToLogIn.accountPassword)
            });

            var loginPostResult = client.PostAsync("https://test.com/login", content).Result;

            loginHTMl = convertToUTF8(loginPostResult.Content.ReadAsStringAsync().Result);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

例外.

无法从传输连接读取数据:无法访问已处置的对象.

Cat*_*lMF 33

经过一番研究后我发现了这个问题.HttpClientHandler将在第一个请求后被释放.您需要指示系统不要处理处理程序.

更改您的使用以添加false到构造函数.

using (var client = new HttpClient(handler, false))
{

}
Run Code Online (Sandbox Code Playgroud)

  • 奇怪,我设置了这个,但似乎没什么区别 (3认同)
  • 不要在 using 语句中使用 `HttpClient`。https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/ (3认同)

小智 6

重用HttpClientHandler实例来防止处理是一种很好的做法.

另外,我个人更喜欢更简洁的语法,最小化Task.Result调用.

// single setup of client handler
HttpClientHandler handler = new HttpClientHandler();

var tasks = eventToCheck.accountsToRunOn.Select(async () => {
    // ...
    using (var client = new HttpClient(handler, false)) // pass false to prevent Disposing
    {
        // ...
        var html = await response.Content.ReadAsStringAsync();
        // ...
        return loginHtml;
    }
});

// get array of results
string[] loginsHtml = await Task.WhenAll(tasks);
Run Code Online (Sandbox Code Playgroud)