2016-04-18 28 views
8

Ho semplificato un po 'il codice, ma fondamentalmente questo continua a darmi un "Impossibile accedere a un oggetto disposto". errore e non riesco a capire perché?Perché questo utilizzo di HttpClient mi dà un "Impossibile accedere a un oggetto disposto". errore?

Ho più attività in esecuzione simultaneamente che eseguono un GET, quindi analizzano alcuni HTML e quindi eseguono un POST in base ai risultati del GET.

Il metodo in cui risiede questo codice restituisce un oggetto evento con risultati, quindi non penso di poterlo attendere perché il metodo dovrebbe restituire void?

loginHTMl = loginPostResult.Content.ReadAsStringAsync(). Risultato è la linea che produce l'errore

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

StackTrace.

System.IO.IOException occurred 
    HResult=-2146232800 
    Message=Unable to read data from the transport connection: Cannot access a disposed object. 
Object name: 'System.Net.Sockets.Socket'.. 
    Source=System 
    StackTrace: 
     at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult) 
    InnerException: 
     HResult=-2146232798 
     Message=Cannot access a disposed object. 
Object name: 'System.Net.Sockets.Socket'. 
     ObjectName=System.Net.Sockets.Socket 
     Source=System 
     StackTrace: 
      at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult, SocketError& errorCode) 
      at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult) 
      at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult) 
     InnerException: 
+0

Quale linea ti dà quell'eccezione? Pubblica l'intera traccia dello stack nella tua domanda. – CathalMF

+0

Puoi pubblicare la traccia dello stack reale dell'eccezione che stai vedendo., – CathalMF

+0

Ho modificato la domanda, speriamo che questo aiuti un po ', fammi sapere cos'altro posso aggiungere :-) – jamie

risposta

16

Ok dopo un po 'di ricerca ho trovato il problema. HttpClientHandler verrà eliminato dopo la prima richiesta. Devi istruire il tuo sistema a non disporre il conduttore.

Modificare l'utilizzo per aggiungere false al costruttore.

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

} 
+0

Strano, ho impostato questo ma non sembra fare la differenza – willem

3

È buona norma riutilizzare l'istanza HttpClientHandler per impedire lo smaltimento.

Inoltre personalmente preferisco una sintassi più chiara con la minimizzazione delle chiamate 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);