我想知道是否有更好的方法将异步数据加载到属性中。现在我创建一个异步函数并在属性的Get部分中引发一个Task,如下所示:
private ObservableCollection<CProyecto> prope;
public ObservableCollection<CProyecto> Prope
{
get
{
if (prope == null)
{
Task.Run(()=> LoadData()).Wait();
}
return proyectos;
}
set
{
prope = value;
RaisePropertyChanged();
}
}
async private Task LoadData()
{
Prope = await clsStaticClassDataLoader.GetDataFromWebService();
}
这种方法有效,但我不喜欢使用.Wait,因为如果服务没有快速响应,它可以冻结屏幕。
你能指导我这件事吗?
提前致谢
答案 0 :(得分:6)
我建议您在async MVVM data-binding上阅读我的MSDN文章。我a library提供NotifyTask<T>
type,可以这样使用:
public class MyClass : INotifyPropertyChanged
{
public NotifyTask<ObservableCollection<CProyecto>> Prope { get; private set; }
public MyClass()
{
// Synchronously *start* the operation.
Prope = NotifyTask.Create(LoadDataAsync());
}
async private Task<ObservableCollection<CProyecto>> LoadDataAsync()
{
return await clsStaticClassDataLoader.GetDataFromWebService();
}
}
然后您的数据绑定将在Prope.Result
上运行。
此方法的优点是您还可以使用数据绑定来隐藏/显示繁忙指示符(Prope.IsNotCompleted
),在数据可用时显示控件(Prope.IsSuccessfullyCompleted
)和错误通知({{ 1}} / Prope.IsFaulted
)。
另外,如果您愿意,可以指定非Prope.ErrorMessage
默认值:
null
答案 1 :(得分:3)
我处理这个的方法是在构造对象时开始加载属性的过程,但我没有等待结果。由于属性在填充时通知,绑定工作正常。基本上它的工作原理如下:
null
这非常有效,并且不会在UI中造成任何延迟或卡顿。如果您希望集合永远不是prope
(IMO的一个好习惯),您可以使用空集合预初始化sudo iptables-save | grep 80
-A IN_public_allow -p tcp -m tcp --dport 80 -m conntrack --ctstate NEW -j ACCEPT
字段。
答案 2 :(得分:0)
您当前对Prope
属性的实现没有多大意义。在后台线程上执行LoadData
方法毫无意义,因为当您调用Wait()
时,无论如何都会阻塞主线程。您也可以直接在Wait()
方法返回的任务上调用LoadData()
:
//BAD IMPLEMENTATION!
private ObservableCollection<CProyecto> prope;
public ObservableCollection<CProyecto> Prope
{
get
{
if (prope == null)
LoadData().Wait();
return proyectos;
}
set { prope = value; RaisePropertyChanged(); }
}
上述实施仍然很糟糕。属性的getter不应该执行异步操作。你应该阅读@Stephen Cleary关于这个主题的博文:https://blog.stephencleary.com/2013/01/async-oop-3-properties.html
...并在NotifyTaskCompletion
库中查看他的AsyncEx
类型:https://github.com/StephenCleary/AsyncEx