2016-06-16 12 views
0

私は非常に新しいasp.netとIQueryableを返そうとしていますが、私はコンテンツを返すよう求めているようです。HttpClient ReadAsAsync <IQueryable <T>>返信することはありません

これは私のコントローラです:

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

    } 

、これは私のクライアント呼び出しです:私はたconnectionStringにmultipleactiveresultsetsを有効にしている

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; 



    } 

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

     RoomsCollection = new ObservableCollection<RumsaRoom>(rooms); 


     return true; 
    } 

LoadAllEntitiesが私のviewmodelのコンストラクタで呼び出されます。 のStatusCodeはGetAllOf()は次のようになります200

方法があります。私はこれに呼び出しを変更した場合 は、それが動作します:それはのIQueryableにReadAsAsyncすることが可能に

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

はありませんか?

おかげ

エリック

答えて

1

あなたの問題は、このコードではほぼ確実である:

LoadAllEntities私のviewmodelのコンストラクタで呼ばれています。

私のブログにはwhy this deadlock happensが詳しく説明されています。 ReadAsAsyncまたはIQueryableとは関係ありません。非同期タスクでWaitまたはResultと呼ぶことと関係しています。要約すると

:そのメソッドが完了したときasyncメソッドによって返さ

  • タスクのみを完了しています。
  • awaitデフォルトでは、「コンテキスト」を取得し、その「コンテキスト」を使用してasyncメソッドを再開します。
  • ASP.NETでは、この「コンテキスト」はAspNetSynchronizationContextのインスタンスであり、一度に1つのスレッドのみを許可します。
  • コードがWait/Resultを呼び出すと、タスクは完了するのを待っているスレッド(ASP.NET要求コンテキストに残っています)をブロックします。
  • awaitがメソッドを再開する準備ができたら、キャプチャされたコンテキストでそれを行い、コンテキストが解放されるのを待ちます。
  • awaitは、コンテキストが解放され、メソッドが完了するまで待機しているスレッドによってコンテキストが使用されるまでメソッドを完了できないため、デッドロックが発生します。

これを解決する正しい方法は、非同期コードをブロックしないことです。代わりにawaitを使用してください。この原則は "async all the way"と呼ばれ、非同期のベストプラクティスに関するMSDNの記事で説明されています。コンストラクターから非同期コードを呼び出そうとしているので、async constructorsのブログ記事を参考にしてください。

関連する問題