UWP C# Асинхронный метод ожидания данных не полностью загружен исключение
Я постараюсь рассказать о своей проблеме как можно более простыми словами. В моем приложении 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, я использую эти данные для загрузки моего вида сетки данными привязки.
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";
}
Проблема, с которой я сталкиваюсь, заключается в том, что когда я запускаю свое приложение, подожду несколько секунд, а затем перейду на страницу библиотеки, все данные будут загружены правильно.
но когда я пытаюсь перейти на страницу библиотеки сразу после запуска приложения, это дает исключение, что
"коллекция была изменена, поэтому она не может быть повторена"
Я использовал точку останова и узнал, что если я дам ей несколько секунд, то данные списка папок будут загружены должным образом асинхронно, но когда я не дам это несколько секунд, этот асинхронный метод будет на половине пути загрузки данных, поэтому вызывает исключение, как я могу справиться с этой асинхронной ситуацией? Спасибо
2 ответа
Что вам нужно, так это способ ожидания получения данных. Как вы вписываетесь в остальную часть приложения (например, MVVM или нет) - это отдельная история, и сейчас это не важно. Не переусердствуйте. Например, вам нужна только ObservableCollection, если вы ожидаете, что данные изменятся, пока пользователь просматривает их.
В любом случае, вам нужно подождать. Так как же вы ждете прибытия этих данных?
Используйте статический класс, который может быть доступен отовсюду. Там положить метод, чтобы получить ваши данные. Убедитесь, что он возвращает задачу, которую вы кэшируете для будущих вызовов. Например:
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();
Когда вам нужны данные на этом другом экране, просто вызовите этот метод снова. Он не будет загружать данные снова (если вы не установили обновление в true), но просто будет ждать завершения работы, которую вы начали ранее, если она еще не завершена.
Я понимаю, что у вас недостаточно опыта. Существует множество проблем, и вы не можете решить, каким образом вы загружаете данные.
Вам нужен сервис, который может предоставить вам ObservableCollection of FolderData. Я думаю, что в этом случае MVVM может выйти за пределы, если вы не готовы потратить на это несколько часов. Хотя в этом случае MVVM сделает все намного проще.
Основная проблема заключается в следующем: вы используете foreach для итерации папок и списка FolderData. Foreach не может продолжаться, если базовая коллекция изменяется.
Во-первых, вам нужно начать использовать цикл for, а не foreach. Во-вторых, добавьте состояние, которое обозначает, закончилась ли загрузка или нет. Наконец, используйте наблюдаемый источник данных. В ранние годы я создавал статические свойства в App.xaml.cs и использовал их для обмена / наблюдения за другими данными.