2016-02-14 2 views
0

У меня есть поток: WebApi> ServiceFramework> DBLayer> MongoDB.Асинхронные блокировочные блоки webapi call

С момента своего нового приложения, я обеспечил асинхронную работу с земли во всех слоях. Однако, когда мой DB Layer имеет асинхронный код, webapi никогда не получает ответ.

API-КОНТРОЛЛЕР

[HttpGet] 
public IHttpActionResult GetAllRecords() 
{ 
    var result = FrameworkApi.GetRecords().Result; 
    return Ok(result); 
} 

выше вызовов> Framework API

public async Task<List<Record>> GetRecords() 
{ 
    return await FrameworkDbApi.GetRecords(); 
} 

выше вызовов> DB Framework API (который вызовы MongoDB)

public async Task<List<Record>> GetRecords() 
{ 
    return await Task.Run(() =>     
     NoSqlDocumentClient.GetDefaultDatabase().Result. 
     GetCollection<Record>("record").AsQueryable().ToList());    

     //following Synchronous version works..but defeats the purpose 
     //return NoSqlDocumentClient.GetDefaultDatabase().Result 
     //  .GetCollection<Record>("record").AsQueryable().ToList(); 
} 

Однако, когда операции в DBLayer или Framework вызывают через тестовый пример, я получаю результат. Но при вызове через контроллер WebApi асинхронная версия никогда не возвращает ответ, в то время как синхронная версия работает нормально.

ответ

2

Но при вызове через контроллер WebApi асинхронная версия никогда возвращает ответ, пока синхронная версия работает нормально.

Это потому, что ваш фактический запрос блокируется. Когда вы вызываете метод через WebAPI, у которого есть SynchronizationContext, вы видите тупик, в отличие от вашего теста, который его не получил, когда тест проходит нормально. Вот почему вы shouldn't block on async code.

Ваш звонок-цепь должна выглядеть так, чтобы избежать запиранием (это то, что это значит идти «асинхронной все пути»:

[HttpGet] 
public async Task<IHttpActionResult> GetAllRecordsAsync() 
{ 
    var result = await FrameworkApi.GetRecordsAsync(); 
    return Ok(result); 
} 

public Task<List<Record>> GetRecordsAsync() 
{ 
    return FrameworkDbApi.GetRecordsAsync(); 
} 

public async Task<List<Record>> GetRecordsAsync() 
{ 
    var result = await NoSqlDocumentClient.GetDefaultDatabase(); 
    return result.GetCollection<Record>("record").AsQueryable().ToList();   
} 
Смежные вопросы