2013-05-17 1 views
2
public class MyClass 
{ 
    MyEntities db = new MyEntities(); 

    public MyClass() 
    { 
     this.Initialise(); // Does not return immediately. Why? 
    } 

    private async void Initialise(); 
    { 
     await this.db.Entities.LoadAsync(); 
    } 
} 

Если я изменяю Initialise использовать ждать Task.Run() для вызова синхронного this.db.Entities.Load(), то он сразу же возвращается, как и ожидался.асинхронного метода недействительный не возвращается немедленно (EF6)

+1

На боковой ноте лучше избегать «async void». У меня есть несколько [альтернативных подходов к инициализации async] (http://blog.stephencleary.com/2013/01/async-oop-2-constructors.html) в моем блоге. –

+0

Этот класс является моделью просмотра и, следовательно, содержит другую информацию о состоянии для вида, например, включены ли кнопки. Мне нужно немедленно вернуть построенный объект или представление будет находиться в неопределенном состоянии. Метод async просто заполняет свойства, которые уже привязаны при построении модели представления, и данные появляются на экране асинхронно. Поскольку это приложение WPF, исключения будут зависеть от контекста синхронизации потока пользовательского интерфейса (в отличие от приложения Windows Phone/Windows 8 Store). – Monstieur

+1

Я понимаю это и повторяю свое предположение, что вы используете асинхронный подход к инициализации. Единственное отличие от 'async void' заключается в том, что вы правильно обрабатываете ошибки (и можете даже обрабатывать исключительные ситуации посредством привязки данных). Приложения WP и Win8 имеют ту же обработку исключений 'async void', что и WPF, - она ​​возникает в потоке' SyncContext' потока пользовательского интерфейса. Но если вы обрабатываете исключения, вы применяете глобальное решение локальной проблемы. –

ответ

5

Код будет выполняться до первой ожидаемой точки (для данных, которые еще не завершены). Имейте в виду, что Initialise эффективно:

var tmp = this.db.Entities.LoadAsync(); 
await tmp; 

Таким образом, мы должны заключить, что LoadAsync принял нетривиальное количество времени, прежде чем он уступил. Что хорошо в пределах API - API await помогает только в том, чтобы все было в порядке; это не гарантирует, что все в неблокирующем. Например, следующие совершенно awaitable:

static Task<int> Evil() { 
    Thread.Sleep(60000); 
    return Task.FromResult(4); 
} 

Это может быть, что данные, контекст загрузки метаданных, погрузочных узлов и т.д. - прежде чем он знает, может ли он дать.

+0

Я считаю, что задержка связана с тем, что Entity Framework разогревается в первый раз, когда используется экземпляр DbContext. Метод LoadAsync(), вероятно, выполняет асинхронное выполнение ввода-вывода базы данных. Прогрев занимает гораздо больше времени, чем любой запрос базы данных в моем приложении. Единственное решение - выполнить «теплый запрос» в полнофункциональной Task.Run(), а затем использовать для последующих методов Async. – Monstieur

 Смежные вопросы

  • Нет связанных вопросов^_^