我怎样才能等到方法完成?

时间:2019-08-20 17:51:45

标签: c# asynchronous async-await

我有一个数据网格和两个组合框。数据网格包含文档,可以拥有文档的第一个组合框人员,第二个组合框具有在第一个组合框中选择的人员的电话号码。

第一个组合框始终包含所有可以拥有文档的人。

如果我未在数据网格中选择文档,但在第一个组合框中选择了一个人,则我想在第二个组合框中填充所选人的所有电话号码。 Bu我不想选择任何电话号码。

如果我在数据网格中选择一个文档,则要在第一个组合框中选择该文档的所有者,并在该文档中设置电话号码。

每次选择文档所有者时,我都会使用一种异步方法来获取数据(电话号码)。代码是这样的:

public Documents SelectedDocumentInDataGrid;
public Persons SelectedPersonInComboBox;
public PhoneNumbers SelectedPhoneNumberInComboBox;

这是我用于将视图绑定到视图模型的属性。我只是显示这个以简化代码。

现在,当我在数据网格中选择一个文档时的代码:

public ObservableCollection<Documents> Documents
{
    get { return _documents; }
    set
    {
        _documents = value;
        base.RaisePropertyChangedEvent("Documents");
    }
}

public Documents DocumentsSelectedItem
{
    get { return _documentsSelectedItem; }
    set
    {
        _documentsSelectedItem = value;
        documentsSelectionChanged();
        base.RaisePropertyChangedEvent("DocumentsSelectedItem");
    }
}


public ObservableCollection<Persons> Owners;
{
    get { return _owners; }
    set
    {
        _owners = value;
        base.RaisePropertyChangedEvent("Owners");
    }
}

public Persons OwnersSelectedItem
{
    get { return _ownersSelectedItem; }
    set
    {
        _ownersSelectedItem = value;
        ownersSelectionChanged();
        base.RaisePropertyChangedEvent("OwnersSelectedItem");
    }
}


public ObservableCollection<PhonesNumbers> PhoneNumbers
{
    get { return _phoneNumbers; }
    set
    {
        _phoneNumbers = value;
        base.RaisePropertyChangedEvent("PhoneNumbers");
    }
}

public PhonesNumbers PhoneNumbersSelectedItem
{
    get { return _phoneNumbersSelectedItem; }
    set
    {
        _phoneNumbersSelectedItem = value;
        base.RaisePropertyChangedEvent("PhoneNumbersSelectedItem");
    }
}




private void documentsSelectionChanged()
{
    OwnersSelectedItem = Owners.FirstOrDefault(x => x.IDPerson == DocumentsSelectedItem?.IDOwner);
    PhoneNumbersSelectedItem = PhoneNumbersSelectedItem.FirstOrDefault(x => x.IDPhoneNumber == DocumentsSelectedItem?.)IDPhoneNumber);
}


private async Task ownersSelectionChanged()
{
    await myRepository.getPhonesNumbersAsync(OwnersSelectedItem?.IDPerson)
        .ContinueWith((myTask) =>
        {
            PhonesNumbers = new ObservableCollection<PhonesNumbers>(await myTask);
        },TaskScheduler.FromCurrentSynchronizationContext());
}

问题在于在OwnersSelectedItem的set属性中调用了异步方法。

原因是,每次选择所有者时,我都想填写电话号码的组合框。而且,如果我选择一个文档,则必须选择所有者和电话号码,这样我就可以重用所选所有者的代码集。

这样,在选择文档时所调用的方法中,我只需要选择所有者,然后选择电话号码即可。

问题在于,在所有者的集合中,我可以使用await,因为它是一个属性,所以当我选择一个文档并设置所有者时,它不必等待完成获取电话号码的过程,因此在下一行中,当我尝试选择电话号码时,我还没有电话号码,因此组合框为空。

我想知道在传递给线路选择电话号码之前,是否有其他方法可以等待完成所有者完成的设置。

谢谢。

2 个答案:

答案 0 :(得分:2)

您不能在C#中拥有async属性,因此不能在属性获取器或设置器中await使用方法。

但是您可以从属性中删除设置器(不允许直接设置),而可以使用async方法进行设置。

public Persons OwnersSelectedItem
{
    get { return _ownersSelectedItem; }
}

public async Task SetOwnersSelectedItem(Person newPerson)
{
    _ownersSelectedItem = newPerson;
    await ownersSelectionChanged();
    base.RaisePropertyChangedEvent("OwnersSelectedItem");
}

答案 1 :(得分:2)

关于代码的一件有趣的事情是,您混合使用了awaitContinueWith

private async Task ownersSelectionChanged()
{
    await myRepository.getPhonesNumbersAsync(OwnersSelectedItem?.IDPerson)
        .ContinueWith((myTask) =>
        {
            PhonesNumbers = new ObservableCollection<PhonesNumbers>(await myTask);
        },TaskScheduler.FromCurrentSynchronizationContext());
}

没有必要这样做-await的目的是在任务完成后恢复您的代码。所以这样的事情应该没问题:

private async Task ownersSelectionChanged()
{
    var phoneNumbers = await myRepository.getPhonesNumbersAsync(OwnersSelectedItem?.IDPerson);

    PhonesNumbers = new ObservableCollection<PhonesNumbers>(phoneNumbers);

    PhoneNumbersSelectedItem = PhonesNumbers.FirstOrDefault(x => x.IDPhoneNumber == DocumentsSelectedItem?.)IDPhoneNumber)
}

请注意,在此处获得列表后,您可以立即选择默认电话号码。这似乎是正确的选择。当用户选择其他所有者时,它将自动发生。

(注意。我已经在PhonesNumbers而不是PhoneNumbersSelectedItem中进行搜索,因为这样做更有意义?)