uwp c#异步方法等待数据未完全加载异常
uwp c# async method waiting data not completely loaded exception
我会尽量用简单的语言来说明我的问题。
在我的 UWP 应用程序中,我在 Mainpage.xaml.cs`
上明智地加载数据
public MainPage()
{
this.InitializeComponent();
LoadVideoLibrary();
}
private async void LoadVideoLibrary()
{
FoldersData = new List<FolderData>();
var folders = (await Windows.Storage.StorageLibrary.GetLibraryAsync
(Windows.Storage.KnownLibraryId.Videos)).Folders;
foreach (var folder in folders)
{
var files = (await folder.GetFilesAsync(Windows.Storage.Search.CommonFileQuery.OrderByDate)).ToList();
FoldersData.Add(new FolderData { files = files, foldername = folder.DisplayName, folderid = folder.FolderRelativeId });
}
}
所以这是我加载 FolderData 对象列表的代码。
在我的其他页面中 Library.xaml.cs 我正在使用该数据通过绑定数据加载我的 gridview。
protected override void OnNavigatedTo(NavigationEventArgs e)
{
try
{
LoadLibraryMenuGrid();
}
catch { }
}
private async void LoadLibraryMenuGrid()
{
MenuGridItems = new ObservableCollection<MenuItemModel>();
var data = MainPage.FoldersData;
foreach (var folder in data)
{
var image = new BitmapImage();
if (folder.files.Count == 0)
{
image.UriSource = new Uri("ms-appx:///Assets/StoreLogo.png");
}
else
{
for (int i = 0; i < folder.files.Count; i++)
{
var thumb = (await folder.files[i].GetThumbnailAsync(Windows.Storage.FileProperties.ThumbnailMode.VideosView));
if (thumb != null) { await image.SetSourceAsync(thumb); break; }
}
}
MenuGridItems.Add(new MenuItemModel
{
numberofvideos = folder.files.Count.ToString(),
folder = folder.foldername,
folderid = folder.folderid,
image = image
});
}
GridHeader = "Library";
}
我面临的问题是,当我启动我的应用程序时,等待几秒钟,然后导航到我的图书馆页面,所有数据都正确加载。
但是当我尝试在启动应用程序后立即导航到图书馆页面时,出现异常
"collection was modified so it cannot be iterated"
我使用了断点,我开始知道如果我给它几秒钟,列表文件夹数据已经正确异步加载,但是当我不给它几秒钟时,异步方法就在一半的路上加载数据导致异常,我该如何处理这种异步情况?谢谢
我知道你没有足够的 experience.There 有多个问题,而且你加载数据的方式没有解决方案。
您需要的是一个可以为您提供 FolderData 的 ObservableCollection 的服务。我认为 MVVM 在这种情况下可能超出范围,除非您愿意花几个小时在上面。尽管在这种情况下 MVVM 会使事情变得容易得多。
手头的主要问题是这个
您正在使用 foreach 迭代文件夹和 FolderData 列表。如果基础集合发生变化,则 Foreach 无法继续。
首先,您需要开始使用 for 循环而不是 foreach。 2nd 添加一个状态,表示加载是否完成。最后使用可观察数据源。在我的早期,我曾经在 App.xaml.cs 中创建静态属性,并且我曾经使用它们来共享/观察其他数据。
您需要的是一种等待数据到达的方法。如何将其与应用程序的其余部分(例如 MVVM 或不)相适应是另一回事,现在并不重要。不要把事情复杂化。例如,如果您希望数据在用户查看时发生变化,则只需要一个 ObservableCollection。
总之,你需要等待。那么您如何等待数据到达?
使用可以从任何地方到达的静态class。在那里放了一个获取数据的方法。确保它 returns 是您缓存以供将来调用的任务。例如:
internal class Data { /* whatever */ }
internal static class DataLoader
{
private static Task<Data> loaderTask;
public static Task<Data> LoadDataAsync(bool refresh = false)
{
if (refresh || loaderTask == null)
{
loaderTask = LoadDataCoreAsync();
}
return loaderTask;
}
private static async Task<Data> LoadDataCoreAsync()
{
// your actual logic goes here
}
}
这样一启动应用就可以开始下载了
await DataLoader.LoadDataAsync();
当您需要另一个屏幕中的数据时,只需再次调用该方法即可。它不会再次下载数据(除非您将刷新设置为真),但会简单地等待您之前开始的工作完成,如果它尚未完成。
我会尽量用简单的语言来说明我的问题。 在我的 UWP 应用程序中,我在 Mainpage.xaml.cs`
上明智地加载数据public MainPage()
{
this.InitializeComponent();
LoadVideoLibrary();
}
private async void LoadVideoLibrary()
{
FoldersData = new List<FolderData>();
var folders = (await Windows.Storage.StorageLibrary.GetLibraryAsync
(Windows.Storage.KnownLibraryId.Videos)).Folders;
foreach (var folder in folders)
{
var files = (await folder.GetFilesAsync(Windows.Storage.Search.CommonFileQuery.OrderByDate)).ToList();
FoldersData.Add(new FolderData { files = files, foldername = folder.DisplayName, folderid = folder.FolderRelativeId });
}
}
所以这是我加载 FolderData 对象列表的代码。 在我的其他页面中 Library.xaml.cs 我正在使用该数据通过绑定数据加载我的 gridview。
protected override void OnNavigatedTo(NavigationEventArgs e)
{
try
{
LoadLibraryMenuGrid();
}
catch { }
}
private async void LoadLibraryMenuGrid()
{
MenuGridItems = new ObservableCollection<MenuItemModel>();
var data = MainPage.FoldersData;
foreach (var folder in data)
{
var image = new BitmapImage();
if (folder.files.Count == 0)
{
image.UriSource = new Uri("ms-appx:///Assets/StoreLogo.png");
}
else
{
for (int i = 0; i < folder.files.Count; i++)
{
var thumb = (await folder.files[i].GetThumbnailAsync(Windows.Storage.FileProperties.ThumbnailMode.VideosView));
if (thumb != null) { await image.SetSourceAsync(thumb); break; }
}
}
MenuGridItems.Add(new MenuItemModel
{
numberofvideos = folder.files.Count.ToString(),
folder = folder.foldername,
folderid = folder.folderid,
image = image
});
}
GridHeader = "Library";
}
我面临的问题是,当我启动我的应用程序时,等待几秒钟,然后导航到我的图书馆页面,所有数据都正确加载。
但是当我尝试在启动应用程序后立即导航到图书馆页面时,出现异常
"collection was modified so it cannot be iterated"
我使用了断点,我开始知道如果我给它几秒钟,列表文件夹数据已经正确异步加载,但是当我不给它几秒钟时,异步方法就在一半的路上加载数据导致异常,我该如何处理这种异步情况?谢谢
我知道你没有足够的 experience.There 有多个问题,而且你加载数据的方式没有解决方案。
您需要的是一个可以为您提供 FolderData 的 ObservableCollection 的服务。我认为 MVVM 在这种情况下可能超出范围,除非您愿意花几个小时在上面。尽管在这种情况下 MVVM 会使事情变得容易得多。
手头的主要问题是这个 您正在使用 foreach 迭代文件夹和 FolderData 列表。如果基础集合发生变化,则 Foreach 无法继续。
首先,您需要开始使用 for 循环而不是 foreach。 2nd 添加一个状态,表示加载是否完成。最后使用可观察数据源。在我的早期,我曾经在 App.xaml.cs 中创建静态属性,并且我曾经使用它们来共享/观察其他数据。
您需要的是一种等待数据到达的方法。如何将其与应用程序的其余部分(例如 MVVM 或不)相适应是另一回事,现在并不重要。不要把事情复杂化。例如,如果您希望数据在用户查看时发生变化,则只需要一个 ObservableCollection。
总之,你需要等待。那么您如何等待数据到达?
使用可以从任何地方到达的静态class。在那里放了一个获取数据的方法。确保它 returns 是您缓存以供将来调用的任务。例如:
internal class Data { /* whatever */ }
internal static class DataLoader
{
private static Task<Data> loaderTask;
public static Task<Data> LoadDataAsync(bool refresh = false)
{
if (refresh || loaderTask == null)
{
loaderTask = LoadDataCoreAsync();
}
return loaderTask;
}
private static async Task<Data> LoadDataCoreAsync()
{
// your actual logic goes here
}
}
这样一启动应用就可以开始下载了
await DataLoader.LoadDataAsync();
当您需要另一个屏幕中的数据时,只需再次调用该方法即可。它不会再次下载数据(除非您将刷新设置为真),但会简单地等待您之前开始的工作完成,如果它尚未完成。