0

Ich arbeite gerade an einer Metro-App, die ein paar textuelle Ressourcen benötigt. Ein Teil des Build-Prozesses kopiert alle diese Ressourcen in einen Ordner innerhalb des Installationsverzeichnisses der App. Ich möchte eine Liste dieser Ressourcendateien sammeln und sie entsprechend bearbeiten. Leider waren meine Versuche weniger erfolgreich.Asynchrone WinRT-Dateioperationen in C++

Da ich für WinRT erstellen, kann ich nicht die sehr nützliche Funktionen "FindFirstFile" und "FindNextFile" verwenden. Ich habe versucht, die Arbeit mit den WinRT Asynchronous File IO-Operationen zu erledigen.

C2664

Fehler:

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 
       } 

      } 

     }); 

    } 

}); 

Welche kompilieren schlägt fehl 'Windows :: Foundation :: IAsyncOperation < TResult> :: Abgeschlossen :: set': kann nicht Parameter 1 von ‚Windows-konvertieren :: Foundation :: AsyncOperationCompletedHandler < TResult> ^‘auf 'Windows :: Foundation :: AsyncOperationCompletedHandler < TResult> ^'

Der Fehler keinen Sinn für mich macht. Ich habe versucht, den obigen Code neu zu schreiben, so dass die Lambda-Handler-Funktionen nicht inline sind, aber es hat keinen Unterschied gemacht. Ich bin mir nicht sicher, was los ist.

Irgendwelche Ideen? Danke im Voraus.

+1

Sie sollten wahrscheinlich 'task ' und seine 'then()' Methode anstelle von dem, was Sie tun. Es wird Ihren Code kürzer und klarer machen. – svick

+0

Mit svick einverstanden: ppl ist dein Freund. –

Antwort

5

[Anmerkung: Ich habe die meisten Namespace Qualifikation von den Code und Fehlermeldungen der Kürze halber weggelassen.]

Die Visual Studio Fehlerlistenfenster zeigt nur die erste Zeile eines jeden Fehler (dies eine sehr nützliche Funktion, vor allem ., wenn in C++ Programmierung, weil einige Fehlermeldungen vom Compiler sehr lange sind Sie müssen sie an dem Ausgabefenster schauen, um den Rest der Fehlermeldung zu sehen:

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 

Dies ist immer noch ein wenig verwirrend, weil alle drei Vorlagen Verwenden Sie einen Parameter mit dem Namen TResult. Um den Fehler zu entziffern, beachten Sie, dass die Reihenfolge o f Die Vorlagen in der ersten Zeile stimmen mit der Reihenfolge der Vorlagenargumentlisten im Rest der Zeile überein. Das Problem besteht darin, dass Sie die Verwendung von StorageFile und IStorageFile mischen. Auf diesen beiden Linien, müssen Sie StorageFile (siehe Möhren unter Linien für wo IStorageFile verwendet wird) verwenden:

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

Beachten Sie, dass, wenn Sie dieses Problem zu beheben, werden Sie ein anderes Paar von Fehlermeldungen erhalten, weil Ihre lambdas brauchen um zwei Parameter zu haben; der zweite ist ein AsyncStatus. Am Ende sollen sie beide deklariert werden als:

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

Da ich für WinRT baue, kann ich nicht die sehr nützlich FindFirstFile und FindNextFile Funktionen nutzen.

Beachten Sie, dass Sie in der Tat, sowohl FindFirstFileEx und FindNextFile in einem Metro-Stil App verwenden. (Die nicht ExFindFirstFile ist nicht verwendbar).

Sie sollten die asynchronen WinRT-Funktionen verwenden, wo immer Sie können und wo immer es sinnvoll ist, aber das bedeutet nicht, dass diese anderen Funktionen nicht verwendet werden können.

+0

Warum haben wir sowohl "Operation" als auch "Status"? Ist "operation-> Status" gleich "status"? – Zingam

4

Eine viel einfachere Lösung ist die Verwendung von PPL für Ihre asynchronen Operationen. Anstatt manuell von dem Asynchron-Betrieb rollen, versuchen:

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 
    } 
}); 

Ich bin nicht 100% auf der Syntax, das in dem SO-Code-Editor geschrieben wurde, aber es zeigt, wie dramatisch PPL die Komplexität dieser Art von Code reduziert - Verwenden Sie im Wesentlichen create_task, um eine Aufgabe zu erstellen, und verwenden Sie dann die Methode .then für die Aufgabe, um ein Lambda anzugeben, das für die asynchrone Beendigung verwendet wird.

BEARBEITEN: Aktualisiert, um das verschachtelte Lambda zu entfernen.

+0

Ich bevorzuge diese Struktur. Danke für den Tipp. – Jeff

+1

Ich habe gerade mit einem PPL-Experten gesprochen (im Büro neben meinem) und es gibt eine bessere Form dafür. Meine Antwort wurde aktualisiert, um dies zu berücksichtigen. –

+0

Super, das sieht gut aus. Danke noch einmal. Schade, dass ich mehrere Antworten nicht akzeptieren kann ... – Jeff