处理异步get方法

时间:2014-08-06 07:53:19

标签: c# windows-runtime windows-phone-8.1

我已经知道这是不可能的。我是C#和WP开发的新手,所以我只想学习最佳实践,以及如何应对这种情况的方法。这是代码:

    public static ObservableCollection<Substance> Substances
    {
        get
        {
            if (_substances == null) await Substance.GetSubstanceDataAsync(); // and nothing gets returned anyway
                else return _substances;
        }
        set
        {
            _substances = value;
        }
    }

我是否应该在App.xaml.cs GetSubstanceDataAsync();方法中调用OnLaunched(),然后对那里的数据进行排序(如果它为空则抛出异常)?或者我应该在每个页面上使用private void NavigationHelper_LoadState(object sender, LoadStateEventArgs e)方法异步并在每次导航页面时检查空值,如果是,则获取数据(这可能是更好的解决方案)?

3 个答案:

答案 0 :(得分:3)

如您所知,您的getter永远不会异步。因此,如果您需要一个资源,您只能通过异步方法,那么getter显然不适合这样做。

您可以做的是让您的属性位于实现INotifyPropertyChanged的ViewModel的实例上。这样,您可以在GetSubstanceDataAsync任务返回时通知侦听器您的Substance属性已更改。非常方便的是,如果在XAML绑定中使用此属性,绑定将自动刷新。

答案 1 :(得分:1)

private ObservableCollection<Substance> _substances;
public static ObservableCollection<Substance> Substances
{
    get
    {
        if (_substances == null) {
           GetSubstanceDataAsync();
        }
        return _substances;
    }
    set
    {
        _substances = value;
    }
}

private async void GetSubstanceDataAsync(){
    Substances = await Substance.GetSubstanceDataAsync();
}

现在,如果您在第一次调用列表时实现INotifyPropertyChanged并且它为空,它将启动异步方法。异步方法完成后,它将更新列表并通知UI有更新。

答案 2 :(得分:1)

根据您实际想要做的事情,有几种不同的可能方法。

如果你想要真正的延迟初始化,那么你应该缓存Task<T>,即使用Lazy<Task<T>>(或AsyncLazy<T> from my AsyncEx library之类的东西)。但是如果这是针对VM类的,那么延迟初始化实际上没有意义(View 总是访问该属性)。

使用VM,您始终可以加载数据,因此您可以在构造函数中开始加载,并在数据到达时更新数据(通过INotifyPropertyChanged / INotifyCollectionChanged)。要记住的重要部分是您希望干净地处理异常。请注意,您的UI将具有(至少)三种不同的状态:加载,成功和错误。当构造函数完成时,它将处于加载状态,然后它将转换为成功或错误状态。

可以对所有这些进行手动编码,或者您可以使用我的MSDN article on async MVVM data binding(也是included in my AsyncEx library)中描述的NotifyTaskCompletion类型。 NotifyTaskCompletion实际上只是一个Task<T>来实现INotifyPropertyChanged,因此您可以在数据绑定完成时成功响应(成功或出错)。