Непрерывное возвращение Observablecollection для медиа-канала C# xamarin
В настоящее время я создаю канал новостей на C# Xamarin.
Медиа-канал - это наблюдаемая коллекция моделей данных для отдельных сообщений.
API, который я использую, довольно ограничен, поэтому я не могу правильно запросить данные, которые мне нужны, что означает, что я получаю много данных. Чтобы пользователи действительно получали достаточно контента, моя коллекция должна запрашивать от 100 до 500 элементов.
Это делает время загрузки чрезвычайно долгим, и я хочу возвращать коллекцию, чтобы постоянно обновлять поток мультимедиа при получении данных из API.
Менеджер каналов
public static async Task<ObservableCollection<PostPresenter>> GetFeed(ApiClient client, string account, int limit = 100)
{
var feed = new ObservableCollection<PostPresenter>();
var feedResult = await ApiClient.FeedClient.GetFeed(account, limit: limit);
if (feedResult != null)
{
foreach (var feedObj in feedResult.Result)
{
if (feedObj != null)
{
var comment = feedObj;
feed.Add(new PostPresenter()
{
Username = comment.Author,
Description = comment?.Title ?? comment.Body?.TruncateString(15) ?? "",
Media = comment.JsonMetadata.Image != null ? comment?.JsonMetadata?.Image.FirstOrDefault() : null,
Tags = comment?.JsonMetadata?.Tags.ToList() ?? new List<string> { "" },
PostTime = comment?.Created.ToString(),
Permlink = comment.Permlink,
EntryId = feedObj.Id
});
}
}
}
foreach (var testObj in feed)
{
await GetFeedMetadata(client, testObj);
}
return feed;
}
Главная страница / Лента новостей
var tempFeedEntries = await FeedManager.GetFeed(User.ApiClient, User.Username);
//var tempFeedEntries = await FeedManager.GetAllFeedData(User.ApiClient, Feed);
if (tempFeedEntries != null)
{
foreach(var tempFeedEntry in tempFeedEntries)
{
Feed.Add(tempFeedEntry);
IsLoading = false;
FeedListViewLoading.IsRunning = false;
FeedListViewLoading.IsRunning = false;
await FeedManager.GetAllFeedData(User.ApiClient, tempFeedEntries);
FeedListView.ItemsSource = Feed;
}
}
Как я могу вернуть временную копию коллекции или сообщений для заполнения канала, не дожидаясь загрузки каждого элемента?
1 ответ
Есть много вещей, которые вы могли бы сделать здесь, но вы не можете использовать yield
в async
метод.
Я бы предложил использовать TPL DataFlow. В основном Dataflow позволяет создавать конвейерные процессоры.
Вы можете создать задание, которое возвращает информацию для других заданий, которое возвращает информацию для других заданий и так далее.
Преимущества
Хорошо работает с
async
а такжеawait
а это значит, что вы можете очень эффективно справиться с этой задачей.Поскольку это, по-видимому, рабочие нагрузки ввода-вывода, он будет эффективно использовать порты завершения ввода-вывода, а не пул потоков для очень эффективного масштабирования.
Вы можете предусмотреть установку максимальной степени параллелизма, чтобы это значение можно было разбить на 10–100 (или более) раз без какого-либо дополнительного кода или накладных расходов, в свою очередь получая все данные из вашего фида (и метаданных) одновременно, не удерживая потоки.
Вы можете указать его для обеспечения порядка, что означает, что он будет работать параллельно, а также будет последовательно возвращать результаты для следующего процессора в конвейере.
Вы можете завершить его блоком действий (без резьбы), который может обновить ваш
ObserverableCollection
с AddRange(хотя я забыл, если этот метод будет уведомлять), также вам нужно будет маршалировать этот вызов обратно в ваш поток пользовательского интерфейса, используяInvoke
,
Даже при недостатке маршаллинга DataFlow сделает это более эффективным и более отзывчивым благодаря нескольким факторам с минимальным количеством кода.
К сожалению, мне просто не хватает информации о ваших типах, API и окружении, чтобы собрать хотя бы маленький пример. Тем не менее, я действительно советую вам пройтись по кривой обучения и изучить этот ценный ресурс и библиотеку TPL.