0

我目前正在开发一个需要一些文本资源的 Metro 应用程序。构建过程的一部分是将所有这些资源复制到应用程序安装目录内的文件夹中。我想做的是收集这些资源文件的列表,并相应地处理每个文件。不幸的是,我这样做的尝试并不成功。

因为我是为 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<结果> ^'

这个错误对我来说没有任何意义。我已经尝试重写上面的代码,以便 lambda 处理程序函数不是内联的,但它没有产生任何影响。我不确定出了什么问题。

有任何想法吗?提前致谢。

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

这仍然有点令人困惑,因为所有三个模板都使用名为TResult. 要破译错误,请注意第一行中模板的顺序与该行其余部分中模板参数列表的顺序相匹配。

这里的问题是您正在混合使用StorageFileand IStorageFile。在这两行中,您需要使用StorageFile(请参阅行下的胡萝卜了解IStorageFile使用位置):

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

请注意,一旦你解决了这个问题,你会得到另一对错误,因为你的 lambdas 需要有两个参数;第二个是AsyncStatus. 最后,它们都应该被声明为:

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

由于我是为 WinRT 构建的,所以我不能使用非常有用的FindFirstFile功能FindNextFile

请注意,事实上,您可以在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任务上的方法来指定用于异步完成的 lambda。

编辑:更新以删除嵌套的 lambda。

于 2012-03-31T15:57:11.610 回答