Tengo una aplicación .Net 4.5 de varios niveles que llama a un método que usa las palabras clave nuevas async
y las await
palabras clave de C # que simplemente se cuelgan y no veo por qué.
En la parte inferior tengo un método asincrónico que amplía nuestra utilidad de base de datos OurDBConn
(básicamente un contenedor para el subyacente DBConnection
y los DBCommand
objetos):
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;
}
Luego tengo un método asincrónico de nivel medio que llama a esto para obtener algunos totales de ejecución 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 tengo un método de UI (una acción MVC) que se ejecuta sincrónicamente:
Task<ResultClass> asyncTask = midLevelClass.GetTotalAsync(...);
// do other stuff that takes a few seconds
ResultClass slowTotal = asyncTask.Result;
El problema es que se cuelga de esa última línea para siempre. Hace lo mismo si llamo asyncTask.Wait()
. Si ejecuto el método SQL lento directamente, tarda unos 4 segundos.
El comportamiento que espero es que cuando llegue asyncTask.Result
, si no está terminado, debe esperar hasta que lo esté, y una vez que lo esté, debe devolver el resultado.
Si paso con un depurador, la declaración SQL se completa y la función lambda finaliza, pero nunca se llega a la return result;
línea de GetTotalAsync
.
¿Alguna idea de lo que estoy haciendo mal?
¿Alguna sugerencia sobre dónde debo investigar para solucionar este problema?
¿Podría ser un punto muerto en alguna parte y, de ser así, hay alguna forma directa de encontrarlo?
SynchronizationContext
.