2015-03-31 6 views
5

Possiedo un progetto universale Windows con più chiamate API. Un metodo si rifiuta di lavorare all'evento in cui le altre chiamate funzionano perfettamente come questo. Ho provato la parola chiave using a pensare che avrebbe risolto il problema.ObjectDisposedException su HttpClient

La funzione:

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; 
     } 
    } 
} 

EDIT

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; 
     } 
    } 
} 

Lo stacktrace

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() 
+1

Perché stai mixando 'await' con' ContinueWith'? –

+0

Perché stai usando 'ContinueWith'? Non è necessario usare 'ContinueWith' quando si ha a che fare con async/await. –

risposta

8

ObjectDisposedException è gettato perché si sta disponendo il HttpRequestMessage e HttpClient prima req.Content.ReadAsStringAsync() finiture.

Si noti che req.Content.ReadAsStringAsync() è un metodo asincrono. È necessario attendere che si completi prima di smaltire lo HttpClient.

Inoltre, ti sembra di chiamare ReadAsStringAsync in req.Content, non dovrebbe essere 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; 
} 

Quasi non v'è alcuna ragione per usare ContinueWith quando si tratta di asincrona/attendono. Tutto ciò che viene fatto dal compilatore per te.

+0

Ok, grazie per il suggerimento, ma ora l'errore è stato generato dopo il risultato var = ... Impossibile accedere a un oggetto disposto. Nome oggetto: 'System.Net.Http.StringContent'. – tim

+0

@SeaSharp Qual è l'eccezione adesso? Pubblica lo stacktrace e il codice aggiornato. –

+0

Fatto. Grazie per l'aiuto già. – tim

4

Si sta accedendo alla richiesta Contenuto, non alla risposta.

Questo

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

dovrebbe essere

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

Troppo tardi :) – tim

4

Il motivo reale della ObjectDisposedException è gettato perché il HttpClient dispone la Content subito dopo una richiesta completata. Dai uno sguardo allo docs.

Quindi, se avete bisogno di leggere il contenuto s' un Request, per esempio nei test, assicurarsi di leggerlo prima di chiamare SendAsync.

+0

Ho colpito anche questo problema.Se provi a riprovare a inviare lo stesso 'Contenuto' due volte (dopo un timeout o simile), ottieni una ObjectDisposedException Per informazioni, sembra che questo sia stato corretto nella fonte di riferimento: https://github.com/ dotnet/corefx/blob/master/src/System.Net.Http/src/System/Net/Http/HttpClient.cs # L517 (sebbene sto ancora vedendo lo stesso problema usando System.Net.Http, Version = 4.0.0.0) –