Fotoğraf tarayıcısı WPF uygulaması - performans iyileştirmeleri
Kişisel bir proje olarak WPF fotoğraf tarayıcı uygulaması üzerinde çalışıyorum. Her seferinde tam görüntüyü okuduğum için küçük resim işleme konusundaki mevcut stratejimin zayıf olduğunun farkındayım - bu, birkaç görüntüden fazla bir klasöre göz atarken gösterilir. Herhangi biri kodun bu yönünü iyileştirebilecek değişiklikler veya başka herhangi bir şey önerebilirse, bu çok yararlı olacaktır.
Kodun inceltilmiş bir versiyonu aşağıdadır. Bu, bir klasörü alır ve içindeki görüntülerin küçük resimlerini ve adlarını görüntüler. (Tam uygulamada ayrıca görüntüler üzerinde çeşitli işlemler gerçekleştirmek için düğmeler bulunur.)
MainWindow.xaml.cs
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Runtime.CompilerServices;
using System.Windows;
namespace PhotoBrowser
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel();
}
}
class MainWindowViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
private string _folder;
public string Folder
{
get => _folder;
set
{
_folder = value;
if (Directory.Exists(_folder))
{
var filesInFolder = Directory.EnumerateFiles(_folder);
var files_ = new ObservableCollection<FileItem>();
foreach (string file in filesInFolder)
{
files_.Add(new FileItem(file, false));
}
Files = files_;
}
else
{
Files = new ObservableCollection<FileItem>();
}
OnPropertyChanged();
}
}
private ObservableCollection<FileItem> _files;
public ObservableCollection<FileItem> Files
{
get => _files;
set
{
_files = value;
OnPropertyChanged();
}
}
public MainWindowViewModel() { }
}
}
MainWindow.xaml
<Window x:Class="PhotoBrowser.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PhotoBrowser"
mc:Ignorable="d"
Title="Photo Browser" Height="800" Width="800" MinHeight="300" MinWidth="400">
<Grid HorizontalAlignment="Stretch" Height="Auto" Margin="10,10,10,10" VerticalAlignment="Stretch" Width="Auto" ShowGridLines="False">
<Grid.RowDefinitions>
<RowDefinition Height="35"/>
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="35"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text="Folder"
Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
<TextBox x:Name="Folder"
Text="{Binding Folder, UpdateSourceTrigger=PropertyChanged}"
Grid.Column="1"
HorizontalAlignment="Stretch" Height="25" TextWrapping="NoWrap" Margin="5,5,5,5"
VerticalAlignment="Center"/>
<ListBox x:Name="FilesInCurrentFolder"
Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Stretch"
BorderBrush="Black" Height="Auto" Width="772" SelectionMode="Extended"
ItemsSource="{Binding Files, UpdateSourceTrigger=PropertyChanged}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Thumbnail}" Width="100" Height="100"/>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected, UpdateSourceTrigger=PropertyChanged}" />
</Style>
</ListBox.Resources>
</ListBox>
</Grid>
</Window>
FileItem.cs
using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Runtime.CompilerServices;
using System.Windows.Media.Imaging;
namespace PhotoBrowser
{
public class FileItem : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
private string _fileName;
public string FileName
{
get => _fileName;
set
{
_fileName = value;
OnPropertyChanged();
OnPropertyChanged("Name");
}
}
private string _name;
public string Name
{
get => Path.GetFileName(_fileName);
set
{
_name = value;
_fileName = Path.Combine(Path.GetDirectoryName(_fileName), value);
OnPropertyChanged();
OnPropertyChanged("FileName");
}
}
private bool _isSelected;
public bool IsSelected
{
get => _isSelected;
set
{
_isSelected = value;
OnPropertyChanged();
}
}
private BitmapSource _thumbnail;
public BitmapSource Thumbnail
{
get => _thumbnail;
set
{
_thumbnail = value;
OnPropertyChanged();
}
}
public FileItem(string fileName)
{
this.FileName = fileName;
GetThumbnail();
}
public FileItem(string fileName, bool isSelected) : this(fileName)
{
this.IsSelected = isSelected;
}
public void GetThumbnail()
{
Image image = new Bitmap(FileName);
image = image.GetThumbnailImage(100, 100, () => false, IntPtr.Zero);
Thumbnail = new BitmapImage(new Uri(FileName));
}
}
}
Yanıtlar
Bence bazı mülk belirleyicileriniz çok şey yapıyor. Örneğin içinde MainWindow
, Folder
özellik belirleyici yalnızca klasör adını ayarlamakla kalmaz, aynı zamanda bu klasördeki tüm dosyaları numaralandırmak ve toplamak da zaman alır. Bu, Tek Sorumluluk İlkesine ve belki de En Az Şaşkınlık İlkesine aykırıdır . Bunun gibi uygulamaları kullandım ve tek yapmak istediğim bir klasöre gitmek olduğunda, ancak her tıklamanın bir klasörden okumaya zorladığı için hayal kırıklığına uğradım. Kısacası, bir klasör belirlemek yalnızca bir klasör belirlemeli ve bu klasördeki dosyaları numaralandırmak ayrı bir işlem olmalıdır.
Performans, bazı eşzamansız çağrıları uygulamaktan ve bazı şeyleri akış halinde tutmaktan fayda sağlayabilir. İle akış EnumerateFiles
yapıyorsunuz ama onları bir listeye ekliyorsunuz. Bu, performans açısından bir darbe alabilir. Dosyaları okumanız gerektiğini düşündüğünüz anı tam olarak araştırır ve o ana kadar okumayı geciktiririm.
İle ilişkili tüm zaman uyumsuz yöntemleri okumalısınız BitMap
. Bu yazıyı bir bit eşlemi C # ile eşzamansız olarak nasıl yükleyeceğimi buluyorum . Dosyaları numaralandırmak veya küçük resimleri yüklemek için bir arka plan Görevi kullanmayı düşünebilirsiniz.