Eu tenho um aplicativo .Net 4.5 multicamadas chamando um método usando C #'s new async
e await
palavras - chave que simplesmente trava e não consigo ver o porquê.
Na parte inferior, tenho um método assíncrono que estende nosso utilitário de banco de dados OurDBConn
(basicamente um wrapper para os objetos DBConnection
e subjacentes DBCommand
):
public static async Task<T> ExecuteAsync<T>(this OurDBConn dataSource, Func<OurDBConn, T> function)
{
string connectionString = dataSource.ConnectionString;
// Start the SQL and pass back to the caller until finished
T result = await Task.Run(
() =>
{
// Copy the SQL connection so that we don't get two commands running at the same time on the same open connection
using (var ds = new OurDBConn(connectionString))
{
return function(ds);
}
});
return result;
}
Então eu tenho um método assíncrono de nível médio que chama isso para obter alguns totais de execução lenta:
public static async Task<ResultClass> GetTotalAsync( ... )
{
var result = await this.DBConnection.ExecuteAsync<ResultClass>(
ds => ds.Execute("select slow running data into result"));
return result;
}
Finalmente, tenho um método de IU (uma ação MVC) que é executado de forma síncrona:
Task<ResultClass> asyncTask = midLevelClass.GetTotalAsync(...);
// do other stuff that takes a few seconds
ResultClass slowTotal = asyncTask.Result;
O problema é que essa última linha fica para sempre. Ele faz a mesma coisa se eu ligar asyncTask.Wait()
. Se eu executar o método SQL lento diretamente, leva cerca de 4 segundos.
O comportamento que estou esperando é que, quando chegar ao fim asyncTask.Result
, se não estiver concluído, espere até que termine e, assim que terminar, retorne o resultado.
Se eu avançar com um depurador, a instrução SQL será concluída e a função lambda será concluída, mas a return result;
linha de GetTotalAsync
nunca será alcançada.
Alguma ideia do que estou fazendo de errado?
Alguma sugestão de onde eu preciso investigar para corrigir isso?
Isso poderia ser um impasse em algum lugar e, se for o caso, existe alguma maneira direta de encontrá-lo?
SynchronizationContext
.