Я создаю MVVM Light WPF-приложение в Visual Studio 2015 с платформой Entity Framework 6. В приложении есть множество моделей просмотра, которые вызывают методы инициализации async
. Вот вид модели пример:Вызов метода async из конструктора модели представления
public class MyViewModel : MyViewModelBase
{
public MyViewModel()
{
PopulateParameters();
// Other code...
}
public ObservableCollection<ParametersViewModel>
Parameters { get; private set; } =
new ObservableCollection<ParametersViewModel>();
private async void PopulateParameters()
{
var service = new MyDataService();
Parameters.Clear();
foreach(var parameter in await service.GetParameters())
Parameters.Add(parameter);
}
// Other methods and properties
}
В MyDataService
класс, у меня есть этот метод:
public async Task<ParametersViewModel> GetParameters()
{
using (var context = new MyEntities())
{
var query = (from param in context.Parameters
select new ParametersViewModel
{
// Populate ParametersViewModel properties here...
}
);
return await Task.Run(() => query);
}
}
Обратите внимание, что конструктор модели представления является Назвав async void
метод PopulateParameters()
. Это очень плохое программирование, и я бы хотел его изменить. Однако я не знаю, как это сделать. Я не могу вводить необходимые данные во все мои модели просмотра; некоторые из них должны выполнить свою собственную инициализацию, большая часть которых связана с вызовами методов async
.
Как изменить приведенный выше код, чтобы соответствовать лучшим методам, когда методы асинхронизации вызывают из конструктора модели представления? Благодарю.
Update: Убедитесь, что вы свяжете на .Result
значения, возвращаемого из NotifyTask.Create()
. Понадобился время, чтобы понять это. Подробнее об этом здесь: https://msdn.microsoft.com/en-us/magazine/dn605875.aspx
Если вы говорите о лучших практиках - что бы вы сделали, когда ваши PopulateParameters выдадут исключение? И это может и произойдет, потому что он говорит о удаленной службе (или базе данных). – Evk
Почему бы не заставить 'PopulateParameters' правильно возвращать' Task' и вызывать его синхронно из конструктора с помощью '.Wait()'? Я пропустил что-то очевидное здесь? Одна вещь, которая кажется интуитивно очевидной, заключается в том, что конструктор никогда не должен вызывать код «асинхронный», который инициализирует объект, - либо сделать синхронизацию инициализации, либо заставить его произойти где-то, кроме конструктора. –
@Evk, спасибо! Ты прав. Как получить исключение и обработать его изящно? Я хотел включить этот вопрос выше, но не сделал :) – Alex