WinRT Асинхронные файловые операции в C ++ - PullRequest
0 голосов
/ 31 марта 2012

В настоящее время я работаю над приложением метро, ​​которое требует нескольких текстовых ресурсов.Частью процесса сборки является копирование всех этих ресурсов в папку внутри установочного каталога приложения.Я хотел бы собрать список этих файлов ресурсов и обработать каждый из них соответствующим образом.К сожалению, мои попытки сделать это были менее чем успешными.

Поскольку я собираюсь для WinRT, я не могу использовать очень полезные функции "FindFirstFile" и "FindNextFile".Я пытался выполнить работу, используя асинхронные операции ввода-вывода WinRT.

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 :: Completed :: set ': невозможно преобразовать параметр 1 из' Windows :: Foundation :: AsyncOperationCompletedHandler ^ 'в' Windows :: Foundation :: AsyncOperationCompletedHandler ^ '

Ошибка не имеет для меня никакого смысла.Я попытался переписать приведенный выше код, чтобы лямбда-функции не были встроенными, но это не имело значения.Я не уверен, что не так.

Есть идеи?Заранее спасибо.

Ответы [ 2 ]

5 голосов
/ 31 марта 2012

[Примечание: для краткости я опустил большинство квалификаций пространства имен в коде и сообщениях об ошибках.]

На панели списка ошибок 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

Это все еще немного сбивает с толку, потому чтовсе три шаблона используют параметр с именем 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 ) {
                                                                             ^

Обратите внимание, что как только вы исправите эту проблему, вы получите еще одну пару ошибок, потому что ваши лямбды должны иметь два параметра, второй - AsyncStatus.В конце они оба должны быть объявлены как:

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

Поскольку я работаю для WinRT, я не могу использовать очень полезные функции FindFirstFile и FindNextFile.

Обратите внимание, что вы можете использовать как FindFirstFileEx, так и FindNextFile в приложении в стиле Metro.(Не Ex FindFirstFile не может использоваться).

Вы должны использовать асинхронные функции WinRT везде, где это возможно и везде, где это возможно, но это не значит, что по-прежнему не используетсядля этих других функций.

4 голосов
/ 31 марта 2012

Гораздо более простым решением является использование 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 в задаче задаете лямбду, которая используется для асинхронного завершения.

РЕДАКТИРОВАТЬ: Обновлено, чтобы удалить вложенную лямбду.

...