У мене багаторівневий додаток .Net 4.5, який викликає метод, використовуючи нове async
і await
ключове слово C #, яке просто висить, і я не можу зрозуміти, чому.
Внизу у мене є метод асинхронізації, який розширює нашу утиліту бази даних 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
.