0

HttpClient(MVCアプリケーション)からGetAllFiles()に電話をかけようとしているときに中括弧の後についてしまいます。私はデバッグモードでデータを見ることができますが、終わりのブレースに到達すると、それは固まってしまいます。WebApiがHttpClientに戻ることができません

私はpostmanから同じWebApiメソッドを呼び出すと、簡単にデータを取得できます。

public class FileToDriveController : ApiController 
{ 
    public IHttpActionResult GetAllFiles() 
    { 
     //Gets credentials 
     GoogleUtility googleUtility = new GoogleUtility(); 
     UserCredential credential = googleUtility.GetCredential(); 

     var service = new DriveService(new BaseClientService.Initializer() 
     { 
      HttpClientInitializer = credential, 
      ApplicationName = "DriveApiFileUpload" 
     }); 

     var listRequest = service.Files.List(); 
     listRequest.MaxResults = 10; 

     IList<Google.Apis.Drive.v2.Data.File> files = listRequest.Execute().Items; 

     if(files!=null) 
     { 
      return Ok(files); //i can see files here in debug mode 
     } 

     return InternalServerError(); 
    } 
} 

これは、APIへのHttpClientの呼び出し

public async Task<HttpResponseMessage> getAllFiles() 
{ 
    using (var client = new HttpClient()) 
    { 
     client.BaseAddress = new Uri("http://localhost:16184/"); 
     client.DefaultRequestHeaders.Accept.Clear(); 
     client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 

     HttpResponseMessage message = await client.GetAsync("api/FileToDrive/GetAllFiles"); 

     if (message.StatusCode == HttpStatusCode.OK) 
     { 
      return message; 
     } 
     return null; 
    } 
} 

答えて

1

あなたの問題は、コントローラ内から非同期呼び出しを行うと、デッドロックによって引き起こされるトリッキーな1です。この優秀な説明を参照してください。http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

トップレベルメソッドはGetJsonAsync(UI/ASP.NETコンテキスト内)を呼び出します。 GetJsonAsyncは、HttpClient.GetStringAsync(まだコンテキスト内)を呼び出してREST要求を開始します。 GetStringAsyncは未完了のタスクを返します。これは、REST要求が完了していないことを示します。 GetJsonAsyncは、GetStringAsyncによって返されたタスクを待機します。コンテキストが取得され、後でGetJsonAsyncメソッドの実行を続行するために使用されます。 GetJsonAsyncメソッドが完了していないことを示すGetJsonAsyncは未完了のTaskを返します。 トップレベルメソッドは、GetJsonAsyncによって返されたタスクを同期してブロックします。コンテキストスレッドをブロックします。 ...最終的に、REST要求は完了します。これで、GetStringAsyncによって返されたタスクが完了します。 GetJsonAsyncの継続が実行可能になり、コンテキストで実行できるようにコンテキストが使用可能になるのを待ちます。 デッドロック。最上位メソッドはコンテキストスレッドをブロックし、GetJsonAsyncが完了するのを待っており、GetJsonAsyncはコンテキストが解放されて完了するのを待っています。

(再び、ブログ記事から取られた)あなたの問題を解決するために:あなたの「ライブラリ」非同期メソッドで

を、ConfigureAwait(false)を可能な限りを使用します。 タスクをブロックしないでください。非同期で使用してください。

+0

ありがとうございます。これは本当に私を助けました。ブログへのリンクが私を助けてくれました。 –

+0

私が最初にそれに遭遇したときにこれを理解しようとすると、頭がおかしくなりました。 – PartlyCloudy

関連する問題