2016-06-16 17 views
0

Im ziemlich neu zu schreiben Controller für asp.net und ich versuche, IQueryable zurückzugeben, aber ich kann nicht scheinen, um den Aufruf für den Inhalt zu erhalten.HttpClient ReadAsAsync <IQueryable <T>> gibt nie zurück

Dies ist mein Controller:

// GET: api/RumsaRooms 
    [EnableQuery] 
    public IQueryable<RumsaRoom> GetRooms() 
    { 
     return db.Rooms; 

    } 

und dies ist mein Client Aufruf:

public async Task<IQueryable<T>> GetAllOf<T>() 
    { 
     var typeName = typeof(T).Name; 



     var result = await _client.GetAsync($"api/{typeName}"); 

     if (!result.IsSuccessStatusCode) 
     { 
      var exception = await result.Content.ReadAsStringAsync(); 


     } 
     //This method never returns 
     var rooms = await result.Content.ReadAsAsync<IQueryable<T>>(); 

     return rooms; 



    } 

Ich habe in der Connectionstring aktiviert Multiple. Der Statuscode ist 200.

Die Methode, die GetAllOf() sieht wie folgt aus:

private async Task<bool> LoadEntities() 
    { 
     var rooms = (await _rumsaClient.GetAllOf<RumsaRoom>()).ToList(); 

     RoomsCollection = new ObservableCollection<RumsaRoom>(rooms); 


     return true; 
    } 

LoadAllEntities im Konstruktor meiner Viewmodel genannt wird. Wenn ich den Anruf an das ändern funktioniert es:

var rooms = await result.Content.ReadAsAsync<List<T>>();

Ist es nicht möglich, eine IQueryable zu ReadAsAsync?

Dank

Erik

Antwort

1

Ihr Problem ist mit ziemlicher Sicherheit in diesem Code:

LoadAllEntities wird im Konstruktor meiner Viewmodel genannt.

Ich erkläre why this deadlock happens im Detail auf meinem Blog. Es hat nichts mit ReadAsAsync oder IQueryable zu tun. Es hat damit zu tun, Wait oder Result für eine asynchrone Aufgabe aufzurufen.

Zusammengefasst:

  • zurück Aufgaben durch async Methoden sind erst dann abgeschlossen, wenn das Verfahren abgeschlossen ist.
  • await erfasst standardmäßig einen "Kontext" und verwendet diesen "Kontext", um die Methode async fortzusetzen.
  • In ASP.NET ist dieser "Kontext" eine Instanz von AspNetSynchronizationContext, die jeweils nur einen Thread gleichzeitig zulässt.
  • Wenn der Code Wait/Result aufruft, blockiert er den Thread (der sich immer noch im ASP.NET-Anforderungskontext befindet) und wartet auf den Abschluss der Task.
  • Wenn die await bereit ist, die Methode fortzusetzen, geschieht dies im erfassten Kontext und wartet darauf, dass der Kontext frei ist.
  • Da await die Methode nicht abschließen kann, bis der Kontext frei ist und der Kontext von einem Thread verwendet wird, der wartet, bis die Methode abgeschlossen ist, wird ein Deadlock angezeigt.

Der richtige Weg, um dies zu lösen, ist nicht auf asynchronen Code zu blockieren; Verwenden Sie stattdessen await.Dieses Prinzip heißt "async all the way" und wird in meinem MSDN-Artikel zu Async-Best Practices beschrieben. Da Sie versuchen, asynchronen Code von einem Konstruktor aufzurufen, finden Sie möglicherweise auch meinen Blogeintrag auf async constructors hilfreich, der einige alternative Ansätze erläutert.