0

私は現在、いくつかのテキストリソースを必要とするメトロアプリに取り組んでいます。ビルドプロセスの一部は、これらすべてのリソースをアプリのインストールディレクトリ内のフォルダーにコピーすることです。私がやりたいのは、これらのリソースファイルのリストを収集し、それに応じてそれぞれを処理することです。残念ながら、そうしようとした私の試みは成功していませんでした。

WinRT用にビルドしているため、非常に便利な「FindFirstFile」関数と「FindNextFile」関数を使用できません。WinRT非同期ファイルIO操作を使用してジョブを実行しようとしています。

auto getResourceFolder = installedLocation->GetFolderFromPathAsync(  folderPath  );

getResourceFolder->Completed = ref new Windows::Foundation::AsyncOperationCompletedHandler< Windows::Storage::StorageFolder^ >( 
[this]( Windows::Foundation::IAsyncOperation< Windows::Storage::StorageFolder^ >^ operation ) {

    if( operation->Status == Windows::Foundation::AsyncStatus::Completed ) {

        auto resourceFolder = operation->GetResults();
        auto getResourceFiles = resourceFolder->GetFilesAsync();
        getResourceFiles->Completed = ref new Windows::Foundation::AsyncOperationCompletedHandler< IVectorView< Windows::Storage::IStorageFile^ >^ >( 
        [this]( Windows::Foundation::IAsyncOperation< IVectorView< Windows::Storage::IStorageFile^ >^ >^ operation ) {

            if( operation->Status == Windows::Foundation::AsyncStatus::Completed ) {

                auto resourceFiles = operation->GetResults();

                for( unsigned int i = 0; i < resourceFiles->Size; ++i ) {

                    // Process File
                }

            }

        });

    }

});

コンパイルに失敗するもの:

エラーC2664:'Windows :: Foundation :: IAsyncOperation <TResult> :: Completed :: set':パラメータ1を'Windows :: Foundation :: AsyncOperationCompletedHandler<TResult>^'から'Windows:: Foundation ::AsyncOperationCompletedHandler<に変換できませんTResult> ^ '

エラーは私には意味がありません。ラムダハンドラー関数がインラインにならないように上記のコードを書き直してみましたが、違いはありません。何が悪いのかわかりません。

何か案は?前もって感謝します。

4

2 に答える 2

5

[注:簡潔にするために、コードとエラーメッセージからほとんどの名前空間の修飾を省略しました。]

Visual Studioの[エラーリスト]ペインには、各エラーの最初の行のみが表示されます(これは、コンパイラからのエラーメッセージが非常に長いため、特にC ++でプログラミングする場合に非常に便利な機能です。出力ウィンドウを見て、エラーメッセージの残りの部分:

error C2664: 'IAsyncOperation<TResult>::Completed::set' : 
cannot convert parameter 1 
    from 'AsyncOperationCompletedHandler<TResult> ^'
    to   'AsyncOperationCompletedHandler<TResult> ^'
with
[
    TResult=IVectorView<StorageFile ^> ^ 
]
and
[
    TResult=IVectorView<IStorageFile ^> ^
]
and
[
    TResult=IVectorView<StorageFile ^> ^
]
No user-defined-conversion operator available, or
Types pointed to are unrelated;
conversion requires reinterpret_cast, C-style cast or function-style cast

3つのテンプレートすべてが。という名前のパラメーターを使用するため、これはまだ少し混乱しますTResult。エラーを解読するには、最初の行のテンプレートの順序が、残りの行のテンプレート引数リストの順序と一致することに注意してください。

ここでの問題は、StorageFileとの使用法が混在していることですIStorageFile。これらの行の両方で、使用する必要がありますStorageFile(使用される場所については、行の下のニンジンを参照してくださいIStorageFile)。

getResourceFiles->Completed = ref new Windows::Foundation::AsyncOperationCompletedHandler< IVectorView< Windows::Storage::IStorageFile^ >^ >( 
                                                                                                                          ^
[this]( Windows::Foundation::IAsyncOperation< IVectorView< Windows::Storage::IStorageFile^ >^ >^ operation ) {
                                                                             ^

この問題を修正すると、ラムダに2つのパラメーターが必要になるため、別のエラーのペアが発生することに注意してください。2番目はAsyncStatusです。最終的には、両方とも次のように宣言する必要があります。

// Namespaces omitted for brevity
[this](IAsyncOperation<StorageFolder^>^ operation, AsyncStatus status) { }

WinRT用に構築しているので、非常に便利な機能を使用できませFindFirstFileFindNextFile

実際には、MetroスタイルアプリFindFirstFileExとの両方を使用できることに注意してください。FindNextFile(非Ex FindFirstFileは使用できません)。

可能な限り、実用的な場所であればどこでも非同期WinRT関数を使用する必要がありますが、それはこれらの他の関数がまだ使用されていないという意味ではありません。

于 2012-03-31T06:45:13.847 に答える
4

はるかに簡単な解決策は、非同期操作にPPLを使用することです。非同期操作を手動で実行する代わりに、次のことを試してください。

create_task(installedLocation->GetFolderFromPathAsync(folderPath)
.then([this](Windows::Storage::StorageFolder^ folder) { 
    return folder->GetFilesAsync();
})
.then([this](IVectorView<Windows::Storage::StorageFile^ >^ files) { 
    for( unsigned int i = 0; i < files->Size; ++i ) { 
         // Process File 
    } 
}); 

私は構文に100%取り組んでいません。これは、SOコードエディターで記述されていますが、PPLがこの種のコードの複雑さを劇的に軽減する方法を示しています。基本的にはcreate_task、タスクの作成に使用し、.thenタスクのメソッドを使用して非同期完了に使用されるラムダを指定します。

編集:ネストされたラムダを削除するように更新されました。

于 2012-03-31T15:57:11.610 に答える