【问题标题】:ObjectDisposedException on HttpClientHttpClient 上的 ObjectDisposedException
【发布时间】:2015-03-31 13:31:16
【问题描述】:

我有一个包含多个 API 调用的 Windows 通用项目。 一种方法拒绝工作,即使我的其他调用完全像这样工作。 我已经尝试了using 关键字,认为它可以解决问题。

功能:

public async Task<User> GetNewUser(string user_guid, OAuthTokens OAuth)
{
    String userguidJSON = VALIDJSON_BELIEVE_ME;
    using (var httpClient = new HttpClient())
    {
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", Encrypt(OAuth.Accesstoken));

        using (HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, BASE_URL + URL_USERS + "/data"))
        {
            req.Content = new StringContent(userguidJSON, Encoding.UTF8, "application/json");
            await httpClient.SendAsync(req).ContinueWith(respTask =>
            {
                Debug.WriteLine(req.Content.ReadAsStringAsync()); //Error is thrown ono this line
            });
            return null;
        }
    }
}

编辑

public async Task<User> GetNewUser(string user_guid, OAuthTokens OAuth)
{
    String userguidJSON = VALIDJSON_BELIEVE_ME;
    using (var httpClient = new HttpClient())
    {
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", Encrypt(OAuth.Accesstoken));

        using (HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, BASE_URL + URL_USERS + "/data"))
        {
            req.Content = new StringContent(userguidJSON, Encoding.UTF8, "application/json");
            await httpClient.SendAsync(req);
            var result = await req.Content.ReadAsStringAsync(); //Cannot access a disposed object. Object name: 'System.Net.Http.StringContent'.
            Debug.WriteLine(result);
            return null;
        }
    }
}

堆栈跟踪

 at System.Net.Http.HttpContent.CheckDisposed()
   at System.Net.Http.HttpContent.ReadAsStringAsync()
   at Roadsmart.Service.RoadsmartService.<GetNewUser>d__2e.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Roadsmart.ViewModel.SettingsPageViewModel.<SetNewProfilePicture>d__1e.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__3(Object state)
   at System.Threading.WinRTSynchronizationContext.Invoker.InvokeCore()

【问题讨论】:

  • 你为什么要把awaitContinueWith混在一起?
  • 你为什么使用ContinueWith?处理 async/await 时不需要使用ContinueWith
  • 请注意,尽管 HttpClient 实现了 IDisposable,但它旨在被实例化一次并在应用程序的整个生命周期内重复使用。

标签: c# mvvm windows-phone-8.1 async-await win-universal-app


【解决方案1】:

ObjectDisposedException 被抛出,因为您要在 req.Content.ReadAsStringAsync() 完成之前处理 HttpRequestMessageHttpClient

请注意,req.Content.ReadAsStringAsync() 是一种异步方法。您需要等待它完成才能处理HttpClient

另外,你好像在req.Content中调用ReadAsStringAsync,不应该是response.Content吗?

using (HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, BASE_URL + URL_USERS + "/data"))
{
    req.Content = new StringContent(userguidJSON, Encoding.UTF8, "application/json");
    var response = await httpClient.SendAsync(req);
    var result = await response.Content.ReadAsStringAsync();//await it
    Debug.WriteLine(result);
    return null;
}

在处理 async/await 时,几乎没有理由使用 ContinueWith。所有这些都由编译器为您完成。

【讨论】:

  • 好的,感谢您的提示,但现在在 var result = ... 无法访问已处置的对象之后引发错误。对象名称:'System.Net.Http.StringContent'。
  • @SeaSharp 现在有什么例外?发布堆栈跟踪和您更新的代码。
  • 在您的代码中,您正在等待req.Content。那不应该是response.Content吗?找到我更新的答案。
  • 啊啊啊!这似乎是罪魁祸首。真傻!有一些代表。很好的帮助!
【解决方案2】:

ObjectDisposedException 被抛出的实际原因是因为HttpClient 在完成请求后立即释放Content。看看docs

因此,如果您需要阅读Request 的内容,例如在测试中,请确保在调用SendAsync 之前阅读它

【讨论】:

  • 我也遇到了这个问题。如果您尝试并重试发送相同的 Content 两次(在超时或类似情况之后),您将收到 ObjectDisposedException 信息,看起来这已在参考源中修复:github.com/dotnet/corefx/blob/master/src/System.Net.Http/src/…(尽管我仍然看到使用 System.Net.Http 的相同问题,版本=4.0.0.0)
  • 使用 System.Net.Http 版本 4.2.0.0 的重试循环时出现同样的问题
  • 原来的问题好像已经在.net core 2.0中修复了。 github.com/dotnet/corefx/pull/19082
【解决方案3】:

您正在访问请求内容,而不是响应。

这个

await httpClient.SendAsync(req);
var result = await req.Content.ReadAsStringAsync(); //Cannot access a disposed object. Object name: 'System.Net.Http.StringContent'.

应该是

var response = httpClient.SendAsync(req);
var result = await response.Content.ReadAsStringAsync();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-23
    • 1970-01-01
    • 2020-06-24
    • 2019-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    相关资源
    最近更新 更多