【发布时间】:2018-12-19 09:19:41
【问题描述】:
In this thread,我可以使用事件来解决我的问题,即在构造函数中等待异步方法。在这种情况下,事件使用不带参数的委托。
但现在我需要等待视图模型完成以等待异步方法可以继续。
我的主视图模型中有这段代码:
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 中的第一行,即 await。
- 主视图模型继续执行代码,因此它不会等待来自数据库的结果。
- 一段时间后,在第二个视图模型中,方法 OnGetDataFromDatabase 完成并在等待之后继续执行下一行代码。
我不明白为什么在第二个视图模型中代码不等到从数据库中获取数据,因为我使用 await 关键字并且所有代码都与帖子的情况相同我在开头链接。
谢谢。
编辑:
如果我使用第二个视图模型的构造函数:
Task.Run(() => buscarDatosAsync(paramFacturaParaImprimir)).Wait();
然后主视图模型等到第二个视图模型完成从数据库中获取数据。
但是当我在第一种情况下尝试这种方法时,在我链接并在另一篇文章中询问的情况下,该方法没有等待,所以我不明白为什么在一种情况下我必须使用委托而在另一种情况下,我可以使用一个任务并等待它完成。
【问题讨论】:
-
可能是因为具有
async/await的方法的void返回类型。没有minimal reproducible example 就很难说。 -
只有实际的事件处理程序允许
async void。但除此之外,基于当前提供的代码没有足够的信息。 -
之前的链接建议是基于在创建对象时自动加载数据的要求,但假设没有其他类依赖于该操作。正如您所经历的那样,这意味着如果实际上存在依赖项,他们将无法等待该异步操作完成。如果打算等待,那么您需要删除先前建议的方法并公开一个有意等待的函数,该函数将由依赖对象调用/调用。
-
另一种方法是创建一个任务完成源并让它监视异步操作,以便它可以等待直到它完成。
-
你真的不应该在构造函数中执行任何
async/await操作,这是非常危险的。无法可靠地判断对象何时完全构建是它所面临的最大问题之一。您应该认真考虑其他模式之一来异步初始化不依赖于构造函数的对象,例如async工厂方法。有一些例子here。如果您绝对必须这样做,该链接为您提供了一种“更安全”的方式来处理它。
标签: c# async-await