我正在尝试编写一个简单的通用应用程序,它可以显示来自网络/ SAN的媒体文件。 我设法让这个东西端到端地工作,我很难以可靠的方式从网络中获取文件。
我感觉这是由于我对C#中的异步和/或XAML应用程序中的数据绑定的不了解,但我无法找到解决方法。
using Windows.Storage;
// Private field to keep files
private BlockingCollection<StorageFile> fileList = new BlockingCollection<StorageFile>();
// Called after page initialization
private async Task InitFilesAsync()
{
var deviceRoot = KnownFolders.MediaServerDevices;
await WalkFolderAsync(deviceRoot);
foreach (var f in fileList)
{
this.lbxFiles.Items.Add(f);
}
}
WalkFolder
方法如下所示:
private async Task WalkFolderAsync(StorageFolder parent)
{
var items = await parent.GetItemsAsync();
foreach(var item in items)
{
if (item.IsOfType(StorageItemTypes.Folder))
{
await WalkFolderAsync((StorageFolder)item);
}
else if (item.IsOfType(StorageItemTypes.File))
{
fileList.Add((StorageFile)item);
}
}
}
在某种程度上工作正常;但有时会有0个文件通过,有时是5个或6个文件,偶尔会有15个文件通过。
更新 我根据评论中的建议略微重构了我的代码,但这没有改进。
更新#2 真的没有运气。看起来像递归异步的东西(或者确实是绑定)可能不是问题;但可能是设备本身?我已经尝试过处理任何等待呼叫异常。我偶尔会拒绝访问,但这又不可重现。
答案 0 :(得分:3)
根本问题是您使用async void
。您应仅使用async void
作为事件处理程序。由于他们不会返回任务,您可以await
直到完成,他们会强制您List
不支持的不需要的多线程。
在迭代之前你也不要等待列表填满,这样你就有了竞争条件。
你应该让你的async
方法返回Task
和await
这些方法,这些方法可以让你的#34;行走&#34;异步但顺序。
private async Task InitFilesAsync()
{
await WalkFolderAsync(KnownFolders.MediaServerDevices);
foreach (var f in fileList)
{
this.lbxFiles.Items.Add(f);
}
}
private async Task WalkFolderAsync(StorageFolder parent)
{
var items = await parent.GetItemsAsync();
foreach(var item in items)
{
if (item.IsOfType(StorageItemTypes.Folder))
{
await WalkFolderAsync((StorageFolder)item);
}
else if (item.IsOfType(StorageItemTypes.File))
{
fileList.Add((StorageFile)item);
}
}
}