C# Забивается оперативная память

414
27 июля 2017, 23:34

Я загружаю изображения 240 штук в ListBox.
Но у меня этот процесс отнимает 1600 мб оперативной памяти и я никак не могу освободить эту память. Другие программы, как к примеру Nvidia Geforce Experience показывает все картинки и оперативную память больше 10-15 мб не занимает

Каким образом можно реализовать показ картинок в папке?

Разметка Xaml

<ListBox x:Name="ListBox_Screenshots"
         ScrollViewer.HorizontalScrollBarVisibility="Disabled"
         ItemContainerStyle="{DynamicResource ListBoxItem_Style}"
         ScrollViewer.VerticalScrollBarVisibility="Hidden"
         Margin="70,10,70,45" Background="#4DFFFFFF" BorderThickness="2,1"
         SelectionMode="Extended" BorderBrush="#FF21AFE4"
         SelectionChanged="ListBox_Screenshots_SelectionChanged"
         MouseDoubleClick="ListBox_Screenshots_MouseDoubleClick">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel ItemHeight="240" ItemWidth="390"
                       Orientation="Horizontal" HorizontalAlignment="Center" />
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Margin="20" HorizontalAlignment="Center">
                <Viewbox>
                    <Image>
                        <Image.Source>
                            <BitmapImage UriSource="{Binding imgSource}"
                                         CacheOption="OnLoad"/>
                        </Image.Source>
                        <Image.Effect>
                            <DropShadowEffect ShadowDepth="2" 
                                              BlurRadius="50"
                                              Color="#FF00249C"/>
                        </Image.Effect>
                    </Image>
                </Viewbox>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Логика C#

//Загружаем все изображения
private void Screenshots_LoadAll()
{
    string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
                + @"\GTA San Andreas User Files\SAMP\screens";
    var dirs = Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories)
                        .Where(s => s.EndsWith(".png") || s.EndsWith(".jpg"));
    foreach (string dir in dirs)
    {
        ListBox_Screenshots.Items.Add(new ImageScreen() { imgSource = dir });
    }
    //Запускаем функцию на ожидание создания или удаления файлов
    Screenshots_StartWatch(path);
}
//Смотрим на создание или удаления файла
private void Screenshots_StartWatch(string path)
{
    FileSystemWatcher watch = new FileSystemWatcher();
    watch.Path = path;
    watch.Created += new FileSystemEventHandler(Screenshots_OnCreated);
    watch.Deleted += new FileSystemEventHandler(Screenshots_OnDeleted);
    watch.EnableRaisingEvents = true;
    bIsScreenshotsWatching = true;
}

public class ImageScreen :IDisposable
{
    public string imgSource { get; set; }
    public void Dispose()
    {
        imgSource = null;
    }
}
Answer 1

Для того чтобы не заморачиваться с созданием миниатюр, сначала рекомендую попробовать воспользоваться штатными средствами WPF.

Класс BitmapImage имеет ряд свойств предназначенных для этого, в частности DecodePixelWidth и DecodePixelHeight

Например, добавление одной строчки:

<ListBox ItemsSource="{Binding Images}">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel ItemHeight="240"
                       ItemWidth="240"
                       Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Image>
                <Image.Source>
                    <BitmapImage UriSource="{Binding}"
                                 CacheOption="OnLoad"
                                 DecodePixelHeight="240"/> <!--Обратите внимание на эту строку-->
                </Image.Source>
            </Image>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Позволило снизить потребление ОЗУ на стандартных обоинах Windows 7 с ~440 до ~95 МБ, причем приложение вообще без картинок занимает ~65 МБ.

До:

После:

READ ALSO
Выбор определенных файлов на флешке без использования OpenFileDialog

Выбор определенных файлов на флешке без использования OpenFileDialog

У нас имеется флешка, требуется вывести в программу все доступные файлы определенного типа (допустим doc, txt) и, при этом, флешки могут отличаться...

284
Как работать с Team Services в Visual Studio?

Как работать с Team Services в Visual Studio?

Разрабатываю проект на C# в Visual StudioМне бы хотелось иметь к нему доступ откуда угодно, чтобы код хранился в облаке

376
Unity ImagePicker iOS

Unity ImagePicker iOS

Пожалуйста обьясните как делается запрос из С# в objective-C и обратно, нужно сделать изменение аватарки в игре с возможностью выбора из галерей...

394
Правильная организация теста и прода

Правильная организация теста и прода

Пишу проектПроект используется на работе в боевых условиях, по-хорошему- должен быть запущен постоянно

269