2014-10-13 15 views
7

Questo è l'errore che ottengo:uno o più errori si sono verificati: PostAsJsonAsync

One or more errors occurred. 
    at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) 
    at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification) 
    at System.Threading.Tasks.Task`1.get_Result() 
    at myProject.mymethod(Int32[] myIds) in path\MyClass.cs:line 758 

Ed ecco che il metodo:

private void mymethod(int[] myIds) 
{ 
    var uri = new Uri(string.Format(UriPath, string.Format(MyPath))); 
    var client = GetHttpClient(uri); 

    var postModel = new PostModel 
    { 
     Ids = myIds, 
     LastUpdate = NewItem ? null : _lastUpdated 
    }; 

    if (client != null) 
    { 
     var response = client.PostAsJsonAsync(uri, postModel).Result;//this line crashes 

     if (response.IsSuccessStatusCode) 
     { 
      //doSomething 
     } 
    } 
} 

io chiamo un sacco di metodi come questo e tutti loro lavorare ad eccezione questo. Quando viene colpito, ci vuole un sacco di tempo e quindi questa eccezione è tiri. Con tutti gli altri metodi l'errore non si verifica.

Questa è l'eccezione interna:

Inner.System.Threading.Tasks.TaskCanceledException: A task was canceled. 

Ecco il mio metodo getClient():

private HttpClient GetHttpClient(Uri uri) 
{ 
    var handler = new HttpClientHandler 
    { 
     CookieContainer = CoockieContainer 
    }; 

    return new HttpClient(handler) 
    { 
     BaseAddress = uri 
    }; 
} 

Ecco il metodo API:

[HttpPost] 
    public IList<MyModel> MyAPIMethod(PostModel model) 
    { 
     List<MyModel> myTranslations; 
     using (var db = new myEntities(GetDbConnStrByUser(new GetCookies().GetUserName()))) 
     { 
      myTranslations = db.tblTranslations.Where(it => model.Ids.Contains(it.id) 
            && (!model.Update.HasValue || it.update > model.LastUpdate.Value)) 
            .Select(it => new MyModel 
            { 
             Id = it.id, 
             Name = it.name, 
             Description = it.desc, 
             LanguageId = it.language_id            
            }).ToList(); 
     } 

     return myTranslations.GroupBy(x => new { x.Id, x.LanguageId }).Select(x => x.First()).ToList(); 
    } 

Forse si verifica un timeout.

Fiddler restituisce questo errore: l'operazione di attesa è scaduta.

+0

non utilizzare il blocco dichiarazioni, andare con asincrono, invece. Guarda l'eccezione interiore. –

+0

@JeroenVannevel Cosa intendi con dichiarazioni bloccanti? –

+0

La chiamata a ".Result" è un'istruzione sincrona; non usi mai l'asincronicità che potresti avere. Più qui sul corretto utilizzo async-await: http://msdn.microsoft.com/en-us/library/hh191443.aspx –

risposta

-1
var client = new HttpClient(); 
var response = await client.PostAsJsonAsync(posturi, postModel); 
bool returnValue = await response.Content.ReadAsAsync<bool>(); 
if (response.IsSuccessStatusCode) { 
    //doSomething 
} 
+0

Scrive il codice per utilizzare async, ma come risolve il problema? C'è qualche motivo per chiamare. Il risultato diretto non funzionerebbe? –

9

.Result cerca di trasformare compito in T. sincrono blocchi in attesa per il compito di completare e tornerà solo T se non si verificano eccezioni. I due tipi di eccezioni che dovresti prevedere sono OperationCanceledExceptions/TaskCanceledExceptions (quando la richiesta HTTP è scaduta o è stato utilizzato un metodo CancellationToken e il token è stato annullato - non penso che quest'ultimo sia applicabile qui) e le eccezioni generali/relative all'HTTP.

Probabilmente stai entrando nello scenario di timeout HTTP. Ci vuole molto tempo prima che l'eccezione venga lanciata? In caso contrario, come è il tuo metodo GetHttpClient? È impostato in modo esplicito timeout o token di cancellazione?

Se si vuole attaccare con l'approccio sincrono e non restituisce le attività, si dovrebbe fare qualcosa di simile a questo, invece:

try 
{  
    var response = client.PostAsJsonAsync(uri, postModel).Result;//this line crashes 
} 
catch (OperationCanceledException oce) 
{ 
    // Tell the user that the request timed our or you cancelled a CancellationToken 
} 
catch (Exception exc) 
{ 
    // Look at the HttpClient docs and try to catch something more specific. You don't want 
    // to swallow StackOverflowExceptions or OutOfMemoryExceptions. 
} 

Se siete disposti a fare il grande passo asincrono, questo è più ciò che si' re cercando:

private async Task mymethodAsync(int[] myIds) 
{ 
    var uri = new Uri(string.Format(UriPath, string.Format(MyPath))); 
    var client = GetHttpClient(uri); 

    var postModel = new PostModel { ... }; 

    if (client != null) 
    { 
     try 
     { 
      var response = await client.PostAsJsonAsync(uri, postModel); 

      if (response.IsSuccessStatusCode) 
      { 
       //doSomething 
      } 
     } 
     catch (OperationCanceledException oce) 
     { 
      // because timeouts are still possible 
     } 
     catch (Exception exc) { 
      // Because other things can still go wrong too (HTTP 500, parsing errors) 
     } 
    } 
} 

Vedi qui per maggiori informazioni su come funziona chiamata .Result w/HttpClient: What happens while waiting on a Task's Result?

+0

L'eccezione interna è TaskCanceledExceptions. La tua prima soluzione in realtà non risolve nulla, aggiunge solo blocchi try-catch. –

+0

sì, ci vuole molto tempo prima che l'eccezione venga lanciata. –

+0

Fiddler restituisce questo errore: l'operazione di attesa è scaduta. –

Problemi correlati