异步方法未等待

时间:2018-07-11 10:54:39

标签: c# async-await

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方法中的第一行,即等待行。
  • 主视图模型继续执行代码,因此它不会等待数据库的结果。
  • 过一会儿,在第二个视图模型中,方法OnGetDataFromDatabase完成,并在等待后继续下一行代码。

我不明白为什么在第二个视图模型中代码不等到从数据库中获取数据,因为我使用的是await关键字,并且所有代码都与发布时相同我在开始时就链接了。

谢谢。

编辑:

如果第二个视图模型的构造函数使用此代码:

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

然后,主视图模型要等到第二个视图模型完成才能从数据库中获取数据。

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

2 个答案:

答案 0 :(得分:4)

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;
}

答案 1 :(得分:1)

假设您正在编写一些基于XAML的代码,那么这里就有一个设计问题。

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

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