我正在反序列化 XML 文件中的对象列表,并希望通过 ViewModel 绑定(bind)到我的 View 中这些对象的实际内容。问题是文件操作是async
这会一直冒泡到 ViewModel,其中属性 getter 不能被标记为这样......
问题
Profile
对象并将它们存储在 List<Profile>
中.此方法(必须)标记为 async
. public static async Task<List<Profile>> GetAllProfiles()
{
DataContractSerializer ser = new DataContractSerializer(typeof(Profile));
StorageFolder folder = await ApplicationData.Current.RoamingFolder.CreateFolderAsync("Profiles", CreationCollisionOption.OpenIfExists);
List<Profile> profiles = new List<Profile>();
foreach (var f in await folder.GetFilesAsync())
{
var fs = await f.OpenStreamForReadAsync();
profiles.Add((Profile)ser.ReadObject(fs));
fs.Dispose();
}
return profiles;
}
理想解决方案 1
public async Task<ObservableCollection<string>> Lists
{
get
{
return new ObservableCollection<string>(GetAllProfiles().Select(p => p.Name));
}
}
async
理想方案2
public ObservableCollection<string> Lists
{
get
{
return new ObservableCollection<string>((GetAllProfiles().Result).Select(p => p.Name));
}
}
await folder.GetFilesAsync()
调用中阻塞)当前解决方案
调用
async
Initialize() 方法加载 GetProfiles()
的结果变量中的函数,然后生成 NotifyPropertyChanged("Lists")
称呼: public ViewModel()
{
Initialize();
}
public async void Initialize()
{
_profiles = await Profile.GetAllProfiles();
NotifyPropertyChanged("Lists");
}
private List<Profile> _profiles;
public ObservableCollection<string> Lists
{
get
{
if (_profiles != null)
return new ObservableCollection<string>(_profiles.Select(p => p.Name));
else
return null;
}
}
问题
有没有更好的办法?
有没有我还没有发现的模式/方法?
编辑
问题的根源出现在做非 UI 代码时,你不能依赖 NotifyPropertyChanged 来做一些线程同步的事情。 -- Initialize 方法必须等待,并且ctors 不能是异步的,所以本质上这是模式是无用的。
public MyClass()
{
Initialize();
}
public async void Initialize()
{
_profiles = await Profile.GetAllProfiles();
}
private ObservableCollection<Profile> _profiles;
public ObservableCollection<string> Lists
{
get
{
return _profiles; // this will always be null
}
}
最佳答案
属性不能是异步的,所以这个解决方案不会像你提到的那样工作。 Task.Result 等待任务完成,但这会阻塞 I/O 操作的异步回调返回的 UI 线程,因此您将死锁您的应用程序,因为从不调用回调。您的解决方案确实是最好的方法。不过可以改进。
关于data-binding - WinRT ViewModel DataBind 到异步方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11849213/