异步方法没有等待



在这个线程中,我可以使用事件来解决在构造函数中等待异步方法的问题。在这种情况下,事件使用不带参数的委托。

但现在我需要等待视图模型完成,等待异步方法才能继续。

我的主视图模型中有以下代码:

public void printMethod()
{
SecondViewModel mySeocViewModel = new SecondViewModel(myParameter);
SecondView mySecondView = new SecondView();
mySecondView.DataContext = mySeocViewModel;
//I have to wait until it finished to can print the user control
//The problem is that this point is reached before mySecondViewModel finish.
}

我的第二个视图模型中的代码:

public docFacturasViewModel(MyType parameter)
{
this.GetDataFromDatabaseEvent += OnGetDataFromDatabase;
GetDataFromDatabaseEvent(parameter);
}

public delegate void GetDataFromDatabaseEventHandler(MyType parameter);
public event GetDataFromDatabaseEventHandler GetDataFromDataBaseEvent;
private async void OnBuscarDatos(MyType paramter)
{
await getDataFromDatabaseAsync(parameter);
//Fill the data of the properties of the view model with the data from database
}

private async Task getDataFromDatabaseAsync(MyType parameter)
{
_myResult = (await getdataAsync(parameter)).FirstOrDefault();
}

如果我调试代码,它以这种方式运行:

  • 它到达主视图模型中的线,以创建第二个视图模型
  • 在第二个视图模型中,它到达方法OnGetDataFromDatabase中的行——第一行,等待
  • 主视图模型继续执行代码,因此它不会等待来自数据库的结果
  • 一段时间后,在第二个视图模型中,方法OnGetDataFromDatabase fnish并在等待后继续下一行代码

我不明白为什么在第二个视图模型中,代码不等到从数据库中获得数据,因为我使用了await关键字,所有代码都与我一开始链接的帖子中的代码相同。

谢谢。

编辑:

如果第二个视图模型的构造函数我使用这个:

Task.Run(() => buscarDatosAsync(paramFacturaParaImprimir)).Wait();

然后主视图模型等待第二个视图模型完成从数据库中获取数据。

但是,当我在第一种情况下尝试这种方法时,在我链接并在另一篇文章中询问的情况下,该方法没有等待,所以我不明白为什么在一种情况下我必须使用委托,而在另一种情况中我可以使用任务并等待它完成。

async void方法到达await时,控件将返回给调用者。显然,当您需要操作的结果来继续处理时,这不是最好的主意。除此之外,我不希望构造函数会产生创建即发即弃任务的副作用。

如果你需要数据的结果作为对象构建的一部分,我建议你采用一种工厂方法:

private SecondViewModel()
{
}
public static async Task<SecondViewModel> CreateAsync(MyType parameter)
{
var result = new SecondViewModel();
result.SomeData = await getDataFromDatabaseAsync(parameter);
return result;
}

你会这样使用它:

public async Task printMethod()
{
SecondViewModel mySeocViewModel = await SecondViewModel.CreateAsync(myParameter);
SecondView mySecondView = new SecondView();
mySecondView.DataContext = mySeocViewModel;
}

假设您正在编写一些基于XAML的代码,则此处存在设计问题。

不要将视图模型创建和数据加载混合使用。通常,您可以同步创建视图模型和视图,并以异步方式加载/发布数据。所以,不要在视图模型构造函数中等待任何东西。

视图模型和视图必须在没有任何数据的情况下正常运行(当数据属性为null或空集合时(。如果在加载数据之前不想访问某些命令,只需禁用这些命令(从CanExecute返回false(。

最新更新