0

Он застревает после того, как закончилась фигурная скобка, когда я пытаюсь позвонить GetAllFiles() из HttpClient (приложение MVC). Я могу видеть данные в режиме отладки, но при достижении конечной скобки он застревает.WebApi не может вернуться в HttpClient

Когда я вызываю тот же метод 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(); 
    } 
} 

Это призыв 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

Ваша проблема сложная одна, которая вызвана взаимоблокировки при выполнении асинхронных вызовов от внутри контроллера. См. Это отличное объяснение: http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

Метод верхнего уровня вызывает GetJsonAsync (в контексте UI/ASP.NET). GetJsonAsync запускает запрос REST, вызывая HttpClient.GetStringAsync (все еще в контексте). GetStringAsync возвращает незавершенную задачу, указывающую, что запрос REST не завершен. GetJsonAsync ожидает задачу, возвращенную GetStringAsync. Контекст захвачен и будет использоваться для продолжения использования метода GetJsonAsync позже. GetJsonAsync возвращает незавершенную задачу, указывая, что метод GetJsonAsync не завершен. Метод верхнего уровня синхронно блокирует задачу, возвращенную GetJsonAsync. Это блокирует контекстный поток. ... В конце концов, запрос REST завершится. Это завершает задачу, которая была возвращена GetStringAsync. Продолжение для GetJsonAsync теперь готово к запуску, и он ожидает, что контекст будет доступен, чтобы он мог выполняться в контексте. Тупик. Метод верхнего уровня блокирует поток контекста, ожидая завершения GetJsonAsync, и GetJsonAsync ожидает, что контекст будет бесплатным, чтобы он мог завершить.

Чтобы решить проблему (опять же, взятый из блога):

В вашей «библиотеки» асинхронными методами, используйте ConfigureAwait (ложь), где это возможно. Не блокируйте задачи; используйте async полностью вниз.

+0

Спасибо Эран. Это очень помогло мне. Мне очень понравилась ссылка на блог. –

+0

У меня возникла серьезная головная боль, пытающаяся понять это, когда я впервые столкнулся с этим, рад, что смогу помочь! – PartlyCloudy