Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Создавайте приложения WinUI с помощью пакета SDK для приложений Windows, которые эффективно обращаются к файловой системе, избегая проблем с производительностью, вызванными задержкой диска и ненужным объемом памяти или загрузкой ЦП.
Если вы хотите получить доступ к большой коллекции файлов и получить доступ к значениям свойств, отличных от стандартных свойств Name, FileType и Path, к ним можно получить доступ, создав QueryOptions и вызвав SetPropertyPrefetch. Метод SetPropertyPrefetch может значительно повысить производительность приложений, отображающих коллекцию элементов, полученных из файловой системы, например коллекцию изображений. В следующем наборе примеров показано несколько способов доступа к нескольким файлам.
Первый пример использует Windows.Storage.StorageFolder.GetFilesAsync для получения сведений об имени набора файлов. Такой подход обеспечивает хорошую производительность, так как пример обращается только к свойству name.
StorageFolder library = Windows.Storage.KnownFolders.PicturesLibrary;
IReadOnlyList<StorageFile> files = await library.GetFilesAsync(Windows.Storage.Search.CommonFileQuery.OrderByDate);
for (int i = 0; i < files.Count; i++)
{
// Do something with the name of each file.
string fileName = files[i].Name;
}
Второй пример использует Windows.Storage.StorageFolder.GetFilesAsync , а затем извлекает свойства образа для каждого файла. Такой подход обеспечивает низкую производительность.
StorageFolder library = Windows.Storage.KnownFolders.PicturesLibrary;
IReadOnlyList<StorageFile> files = await library.GetFilesAsync(Windows.Storage.Search.CommonFileQuery.OrderByDate);
for (int i = 0; i < files.Count; i++)
{
ImageProperties imgProps = await files[i].Properties.GetImagePropertiesAsync();
// Do something with the date the image was taken.
DateTimeOffset date = imgProps.DateTaken;
}
Третий пример использует QueryOptions для получения сведений о наборе файлов. Этот подход обеспечивает гораздо лучшую производительность, чем предыдущий пример.
// Set QueryOptions to prefetch our specific properties.
var queryOptions = new Windows.Storage.Search.QueryOptions(CommonFileQuery.OrderByDate, null);
queryOptions.SetThumbnailPrefetch(
ThumbnailMode.PicturesView,
100,
ThumbnailOptions.ReturnOnlyIfCached);
queryOptions.SetPropertyPrefetch(
PropertyPrefetchOptions.ImageProperties,
new string[] { "System.Size" });
StorageFileQueryResult queryResults = KnownFolders.PicturesLibrary.CreateFileQueryWithOptions(queryOptions);
IReadOnlyList<StorageFile> files = await queryResults.GetFilesAsync();
foreach (var file in files)
{
ImageProperties imageProperties = await file.Properties.GetImagePropertiesAsync();
// Do something with the date the image was taken.
DateTimeOffset dateTaken = imageProperties.DateTaken;
// Performance gains increase with the number of properties that are accessed.
IDictionary<string, object> propertyResults =
await file.Properties.RetrievePropertiesAsync(new string[] { "System.Size" });
// Get or set extra properties here.
var systemSize = propertyResults["System.Size"];
}
Если вы выполняете несколько операций с объектами Windows.Storage, например Windows.Storage.ApplicationData.Current.LocalFolder, создайте локальную переменную, чтобы ссылаться на источник хранилища, чтобы не создавать промежуточные объекты при каждом доступе к нему.
Потоковая производительность в C#
Буферизация между потоками среды выполнения Windows и .NET
Существует множество сценариев, когда может потребоваться преобразовать поток среды выполнения Windows (например, Windows.Storage.Streams.IInputStream или IOutputStream) в поток .NET (System.IO.Stream). Например, это полезно при написании приложения WinUI и необходимости использовать существующий код .NET, который работает с потоками с API службы хранилища Windows. Для этого .NET предоставляет методы расширения, позволяющие преобразовать типы потоков среды выполнения .NET и Windows. Дополнительные сведения см. в разделе WindowsRuntimeStreamExtensions.
При преобразовании потока среды выполнения Windows в поток .NET вы фактически создаете адаптер для базового потока среды выполнения Windows. В некоторых случаях стоимость среды выполнения связана с вызовом методов в потоках среды выполнения Windows. Это может повлиять на скорость приложения, особенно в сценариях, где выполняется множество небольших, частых операций чтения или записи.
Чтобы ускорить работу приложений, адаптеры потоков среды выполнения Windows содержат буфер данных. В следующем примере кода показаны небольшие последовательные операции чтения с помощью адаптера потока среды выполнения Windows с размером буфера по умолчанию.
StorageFile file = await Windows.Storage.ApplicationData.Current
.LocalFolder.GetFileAsync("example.txt");
Windows.Storage.Streams.IInputStream windowsRuntimeStream =
await file.OpenReadAsync();
byte[] destinationArray = new byte[8];
// Create an adapter with the default buffer size.
using (var managedStream = windowsRuntimeStream.AsStreamForRead())
{
// Read 8 bytes into destinationArray.
// A larger block is actually read from the underlying
// windowsRuntimeStream and buffered within the adapter.
await managedStream.ReadAsync(destinationArray, 0, 8);
// Read 8 more bytes into destinationArray.
// This call may complete much faster than the first call
// because the data is buffered and no call to the
// underlying windowsRuntimeStream needs to be made.
await managedStream.ReadAsync(destinationArray, 0, 8);
}
Это поведение буферизации по умолчанию желательно в большинстве сценариев, когда поток среды выполнения Windows преобразуется в поток .NET. Однако в некоторых сценариях может потребоваться настроить поведение буферизации, чтобы повысить производительность.
Работа с большими наборами данных
При чтении или записи больших наборов данных можно увеличить пропускную способность чтения или записи, предоставив большой размер буфера методам расширения AsStreamForRead, AsStreamForWrite и AsStream . Это дает адаптеру потока больший размер внутреннего буфера. Например, при передаче потока, который поступает из большого файла в средство синтаксического анализа XML, средство синтаксического анализа может сделать много последовательных небольших операций чтения из потока. Большой буфер может уменьшить количество вызовов в базовом потоке среды выполнения Windows и повысить производительность.
Замечание
Будьте осторожны при настройке размера буфера, превышающего приблизительно 80 КБ, так как это может привести к фрагментации в куче сборщика мусора. Дополнительные сведения см. в разделе "Повышение производительности сборки мусора" в приложениях WinUI. В следующем примере кода создается управляемый адаптер потока с буфером 81 920 байтов.
// Create a stream adapter with an 80 KB buffer.
Stream managedStream = nativeStream.AsStreamForRead(bufferSize: 81920);
Методы Stream.CopyTo и CopyToAsync также выделяют локальный буфер для копирования между потоками. Как и в случае с методом расширения AsStreamForRead , вы можете повысить производительность для больших копий потоков, переопределив размер буфера по умолчанию. В следующем примере кода показано изменение размера буфера по умолчанию вызова CopyToAsync .
MemoryStream destination = new MemoryStream();
// Copies the buffer into memory using the default copy buffer.
await managedStream.CopyToAsync(destination);
// Copy the buffer into memory using a 1 MB copy buffer.
await managedStream.CopyToAsync(destination, bufferSize: 1024 * 1024);
В этом примере используется размер буфера размером 1 МБ, который больше 80 КБ, рекомендуемых ранее. Использование такого большого буфера может повысить пропускную способность операции копирования для очень больших наборов данных (т. е. несколько сотен мегабайт). Однако этот буфер выделяется в куче больших объектов и может привести к снижению производительности сборки мусора. Следует использовать большие размеры буферов только в том случае, если они заметно повышают производительность приложения.
При одновременной работе с большим количеством потоков может потребоваться уменьшить или исключить затраты на память буфера. Можно указать меньший буфер или задать параметр bufferSize равным 0, чтобы полностью отключить буферизацию для этого адаптера потока. Вы по-прежнему можете обеспечить высокую производительность пропускной способности без буферизации при выполнении больших операций чтения и записи в управляемый поток.
Выполнение операций с учетом задержки
Кроме того, можно избежать буферизации, если требуется низкая задержка чтения и записи, а также не требуется считывать большие блоки из базового потока среды выполнения Windows. Например, при использовании потока для сетевого обмена данными может потребоваться низкая задержка чтения и записи.
В приложении чата можно использовать поток через сетевой интерфейс для отправки сообщений обратно и вперед. В этом случае вы хотите отправлять сообщения сразу после их готовности и не дождитесь заполнения буфера. Если при вызове методов расширения AsStreamForRead, AsStreamForWrite и AsStream задано значение 0, то результирующий адаптер не выделяет буфер, а все вызовы будут управлять базовым потоком среды выполнения Windows напрямую.
Windows developer