次の方法で共有


WinUI のファイル プロパティへの高速アクセス

ライブラリからファイルとそのプロパティの一覧をすばやく収集し、それらのプロパティをアプリで使用する方法について説明します。  

前提条件

  • WinUI アプリの非同期プログラミング C# で非同期アプリを記述する方法については、「C # または Visual Basic での非同期 API の呼び出し」を参照してください。 C++ で非同期アプリを記述する方法については、「C++での非同期プログラミング」を参照してください。 
  • ライブラリへのアクセス許可 これらの例のコードには picturesLibrary 機能が必要ですが、ファイルの場所に別の機能が必要な場合や、まったく機能が必要な場合があります。 詳細については、「 ファイル アクセス許可」を参照してください。 
  • 単純なファイル列挙 この例では 、QueryOptions を 使用して、いくつかの高度な列挙プロパティを設定します。 小さいディレクトリのファイルの単純な一覧を取得する方法の詳細については、「 ファイルとフォルダーを列挙してクエリを実行する」を参照してください。 

使用

多くのアプリでは、ファイルのグループのプロパティを一覧表示する必要がありますが、常にファイルを直接操作する必要はありません。 たとえば、音楽アプリは一度に 1 つのファイルを再生 (開く) しますが、アプリが曲キューを表示できるように、またはユーザーが再生する有効なファイルを選択できるように、フォルダー内のすべてのファイルのプロパティが必要です。

このページの例は、プロパティの読み取り以外に、結果として得られるすべての StorageFile と対話するすべてのファイルまたはアプリのメタデータを変更するアプリでは使用しないでください。 詳細については、「 ファイルとフォルダーの列挙とクエリ 」を参照してください。 

場所内のすべての図を列挙する

この例では、

  • QueryOptions オブジェクトをビルドして、アプリが可能な限り迅速にファイルを列挙することを指定します。
  • StorageFile オブジェクトを順次アプリに読み込み、ファイルのプロパティを取得します。 ファイルをメモリに読み込むことで、アプリの使用メモリが減少し、体感応答性が向上します。

クエリの作成

クエリを作成するには、QueryOptions オブジェクトを使用して、アプリが特定の種類のイメージ ファイルのみを列挙することを指定し、Windows Information Protection (System.Security.EncryptionOwners) で保護されたファイルを除外します。 

アプリが QueryOptions.SetPropertyPrefetch を使用してアクセスするプロパティを設定することが重要です。 プリフェッチされていないプロパティにアプリがアクセスすると、パフォーマンスが大幅に低下します。

IndexerOption.OnlyUseIndexerAndOptimzeForIndexedProperties を設定すると、可能な限り迅速に結果を返すが、SetPropertyPrefetch で指定されたプロパティのみを含むようにシステムに指示されます。

結果のページング

ユーザーは画像ライブラリに数千または数百万のファイルを含む可能性があるため、 GetFilesAsync を 呼び出すと、イメージごとに StorageFile が作成されるため、コンピューターが過剰に使用されます。 これは、一度に固定数の StorageFile を作成し、UI に処理してからメモリを解放することで解決できます。 

この例では、 StorageFileQueryResult.GetFilesAsync(UInt32 StartIndex, UInt32 maxNumberOfItems) を使用して、一度に 100 個のファイルのみをフェッチします。 その後、アプリはファイルを処理し、その後 OS がそのメモリを解放できるようにします。 この手法は、アプリの最大メモリを制限し、システムの応答性を維持します。 もちろん、シナリオに対して返されるファイルの数を調整する必要がありますが、すべてのユーザーに応答性の高いエクスペリエンスを確保するには、一度に 500 を超えるファイルをフェッチしないことをお勧めします。

StorageFolder folderToEnumerate = KnownFolders.PicturesLibrary; 
// Check if the folder is indexed before doing anything. 
IndexedState folderIndexedState = await folderToEnumerate.GetIndexedStateAsync(); 
if (folderIndexedState == IndexedState.NotIndexed || folderIndexedState == IndexedState.Unknown) 
{ 
    // Only possible in indexed directories.  
    return; 
} 
 
QueryOptions picturesQuery = new QueryOptions() 
{ 
    FolderDepth = FolderDepth.Deep, 
    // Filter out all files that have WIP enabled
    ApplicationSearchFilter = "System.Security.EncryptionOwners:[]", 
    IndexerOption = IndexerOption.OnlyUseIndexerAndOptimizeForIndexedProperties 
}; 

picturesQuery.FileTypeFilter.Add(".jpg"); 
string[] otherProperties = new string[] 
{ 
    SystemProperties.GPS.LatitudeDecimal, 
    SystemProperties.GPS.LongitudeDecimal 
}; 
 
picturesQuery.SetPropertyPrefetch(PropertyPrefetchOptions.BasicProperties | PropertyPrefetchOptions.ImageProperties, 
                                    otherProperties); 
SortEntry sortOrder = new SortEntry() 
{ 
    AscendingOrder = true, 
    PropertyName = "System.FileName" // FileName property is used as an example. Any property can be used here.  
}; 
picturesQuery.SortOrder.Add(sortOrder); 
 
// Create the query and get the results 
uint index = 0; 
const uint stepSize = 100; 
if (!folderToEnumerate.AreQueryOptionsSupported(picturesQuery)) 
{ 
    log("Querying for a sort order is not supported in this location"); 
    picturesQuery.SortOrder.Clear(); 
} 
StorageFileQueryResult queryResult = folderToEnumerate.CreateFileQueryWithOptions(picturesQuery); 
IReadOnlyList<StorageFile> images = await queryResult.GetFilesAsync(index, stepSize); 
while (images.Count != 0 || index < 10000) 
{ 
    foreach (StorageFile file in images) 
    { 
        // With the OnlyUseIndexerAndOptimizeForIndexedProperties set, this won't  
        // be async. It will run synchronously. 
        var imageProps = await file.Properties.GetImagePropertiesAsync(); 
 
        // Build the UI 
        log(String.Format("{0} at {1}, {2}", 
                    file.Path, 
                    imageProps.Latitude, 
                    imageProps.Longitude)); 
    } 
    index += stepSize; 
    images = await queryResult.GetFilesAsync(index, stepSize); 
} 

結果

結果の StorageFile ファイルには、要求されたプロパティのみが含まれますが、他の IndexerOptions と比較して 10 倍高速に返されます。 アプリはまだクエリに含まれていないプロパティへのアクセスを要求できますが、ファイルを開いてそれらのプロパティを取得する場合、パフォーマンスが低下します。  

ライブラリへのフォルダーの追加

アプリは、 StorageLibrary.RequestAddFolderAsync を使用して、インデックスに場所を追加するようにユーザーに要求できます。 場所が含まれると、自動的にインデックスが作成され、アプリはこの手法を使用してファイルを列挙できます。  

こちらも参照ください

QueryOptions API リファレンス
ファイルとフォルダーを列挙してクエリを実行する
ファイル アクセス許可