У меня есть многоуровневое приложение .Net 4.5, вызывающее метод с использованием ключевых слов C # new async
и, await
которые просто зависают, и я не понимаю, почему.
Внизу у меня есть асинхронный метод, который расширяет нашу утилиту базы данных OurDBConn
(в основном оболочка для базовых объектов DBConnection
и 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;
}
Затем у меня есть асинхронный метод среднего уровня, который вызывает это, чтобы получить некоторые медленные итоги:
public static async Task<ResultClass> GetTotalAsync( ... )
{
var result = await this.DBConnection.ExecuteAsync<ResultClass>(
ds => ds.Execute("select slow running data into result"));
return result;
}
Наконец, у меня есть метод пользовательского интерфейса (действие MVC), который выполняется синхронно:
Task<ResultClass> asyncTask = midLevelClass.GetTotalAsync(...);
// do other stuff that takes a few seconds
ResultClass slowTotal = asyncTask.Result;
Проблема в том, что он навсегда висит на последней строке. То же самое происходит, если я звоню asyncTask.Wait()
. Если я запустил медленный метод SQL напрямую, это займет около 4 секунд.
Я ожидаю, что когда это произойдет asyncTask.Result
, если он еще не закончен, он должен подождать, пока он не закончится, и, как только это произойдет, он должен вернуть результат.
Если я перейду через отладчик, оператор SQL завершится и лямбда-функция завершится, но return result;
строка GetTotalAsync
никогда не будет достигнута.
Есть идеи, что я делаю не так?
Есть предложения, где мне нужно изучить, чтобы это исправить?
Может быть, это где-то тупик, и если да, то есть ли прямой способ его найти?
SynchronizationContext
.