0

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

Поскольку я создаю для WinRT, я не могу использовать очень полезные функции FindFirstFile и FindNextFile. Я пытался выполнить эту работу с помощью операций ввода-вывода WinRT Asynchronous file 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> :: Прошлые :: набор': не удается преобразовать параметр 1 из «Windows :: Foundation :: AsyncOperationCompletedHandler < TResult> ^»к 'Windows :: Foundation :: AsyncOperationCompletedHandler < TResult> ^'

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

Любые идеи? Заранее спасибо.

+1

Возможно, вы должны использовать 'task ' и свой 'then()' вместо того, что вы делаете. Это сделает ваш код короче и понятнее. – svick

+0

Согласен с svick: ppl - ваш друг. –

ответ

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 

Это еще немного сбивает с толку, потому что все три шаблона используйте параметр с именем TResult. Чтобы расшифровать ошибку, обратите внимание, что порядок o f шаблоны в первой строке соответствуют порядку списков аргументов шаблона в остальной части строки.

Проблема заключается в том, что вы смешиваете использование 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. (Не ExFindFirstFile не может быть использован).

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

+0

Почему у нас есть «операция» и «статус»? Является ли 'operation-> Status' равным' status'? – Zingam

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% по сравнению с синтаксисом, это было написано в СЦ редактор кода, но он показывает, как PPL значительно снижает сложность такого кода - в основном вы используете create_task для создания задачи, а затем используйте метод .then для задания, чтобы указать лямбду, которая используется для завершения асинхронизации.

EDIT: Обновлен для удаления вложенной лямбда.

+0

Я предпочитаю эту структуру. Спасибо за совет. – Jeff

+1

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

+0

Удивительный, это отлично выглядит. Еще раз спасибо. Жаль, что я не могу принять несколько ответов ... – Jeff

Смежные вопросы