разместить растровое изображение в массиве с помощью linq - PullRequest
1 голос
/ 05 мая 2020

У меня есть массив из 3500 растровых изображений. Эти растровые изображения отображаются на экране (на экране может отображаться 12 изображений), и загружаются другие изображения, когда вертикальная полоса прокрутки опускается вниз. В какой-то момент я хотел бы освободить эти изображения из памяти, и я хотел бы знать, может ли Linq помочь: Что я пробовал:

Объявление:

    imageCache = new Bitmap[someCountWithaResultOf3500];

загружается imageCache по изображениям, а затем в какой-то момент я хотел бы избавиться от нескольких (от начала до 200 до текущего). Id сообщает мне первое отображаемое изображение.

Функция

imageCache.AsEnumerable()
                   .Select((s, j) => new { j, s })
                   .Where(x => (x.j > 0 && x.j < lowlimit && x.j != null))
                   .ToList().ForEach(x => Dispose());

lowlimit - это максимальное значение 0 и id -200 отображаемого изображения.

Когда Я достиг нижнего предела, экран становится черным, изображения исчезают (в режиме отладки у меня было lowlimit на 4)

2 вопроса:

  • в предложении where, Я хотел бы отфильтровать не удаленные растровые изображения, как это сделать (мой пункт x.j !=null не работает)
  • Должно ли работать Dispose в foreach?

1 Ответ

1 голос
/ 05 мая 2020

Ключевой вопрос - как определить, когда изображения могут быть выгружены.

Возьмем наивный пример ... Если изображение видно, оно будет сохранено в памяти, в противном случае выгрузить его.

(Это не будет идеальным вариантом, поскольку каждый раз при прокрутке изображения необходимо повторно загружать с диска, но он демонстрирует подход)

Допустим, у нас есть функция, которая определяет, какие изображения находятся в просмотреть и вернуть список путей [также могут быть идентификаторы] ....

public List<string> GetVisibleImagePaths() {
    //Do something here to return a dozen or so paths that are visible.

    //Later refinement: Also include images a few either side of the current position for 
    //smoother scrolling
}

Итак ....

Когда кто-то изменяет положение прокрутки вашего элемента управления

protected override void OnScroll(ScrollEventArgs se) {
    base.OnScroll(se);
    EvictFromCache();
}

private Dictionary<string, Bitmap> imageCache;

private void EvictFromCache() {
    var paths = GetVisibleImagePaths();
    // Now loop through all the keys in the cache and evict those not specifically requested
    // This is a naive approach to cache eviction. Perhaps you want to keep the last few dozen
    // in case the user reverses direction and scrolls back or .... Lots of options, but for now
    // we'll evict anything not in the list of paths we were given
    foreach (var expired in imageCache.Keys.Where(x => !paths.Contains(x)).ToList()) {
        //Dispose of the object, freeing up resources
        imageCache[expired].Dispose();

        //And now remove the reference to the disposed object
        imageCache.Remove(expired);
    }
}

Вам нужно будет выполнить некоторую настройку, чтобы выработать оптимальное соотношение между тем, сколько хранить в кеше / насколько заблаговременно загружать изображения, чтобы обеспечить оптимальный баланс производительности / скорости отклика на целевом оборудовании .

Кроме того, делать это при прокрутке на самом деле необязательно .... Просто нерегулярно, но это было удобно для демонстрационных целей. В зависимости от выбранной стратегии, таймер или другой подход может быть более подходящим.

Один момент для определения того, что что-то удалено ... Не надо. Как только вы избавитесь от объекта, освободите все ссылки на него. Если вам нужен новый, вам все равно придется создать его fre sh, поэтому сохранять ссылку на непригодный для использования объект бессмысленно.

Вместо того, чтобы проверять, удален ли объект, проверьте, есть ли у вас объект, на который ссылаются вообще (это ноль / существует ли ключ / пустой список / et c)

Это обрабатывается выше путем удаления, а затем удаления из словаря.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...