0

저는 현재 텍스트 리소스가 필요한 메트로 앱을 만들고 있습니다. 빌드 프로세스의 일부는 이러한 모든 리소스를 앱의 설치 디렉토리 안의 폴더에 복사하는 것입니다. 내가하고 싶은 것은 이러한 리소스 파일의 목록을 수집하고 이에 따라 각 리소스 파일을 처리하는 것입니다. 불행히도 그렇게하려는 나의 시도는 성공적이지 못했습니다.C++의 WinRT 비동기 파일 작업

저는 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를 : '윈도우 :: 재단 :: IAsyncOperation < TResult> :: 완료 :: 설정': '윈도우에서 매개 변수 1 변환 할 수 없습니다 :: 재단 :: AsyncOperationCompletedHandler < TResult>^윈도우 :: '에서'재단 :: AsyncOperationCompletedHandler < TResult>^'오류가 나에게 어떤 의미를 만드는되지

. 위의 코드를 다시 작성하여 람다 처리기 함수가 인라인이 아니지만 차이를 만들지 않았습니다. 나는 틀린 것이 확실하지 않다.

아이디어가 있으십니까? 미리 감사드립니다.

+1

당신이하는 일보다는'task '와'then()'메쏘드를 사용해야합니다. 코드를 더 짧고 명확하게 만듭니다. – svick

+0

svick 동의 : ppl은 당신의 친구입니다. –

답변

5

[참고 : 나는 간결에 대한 코드 및 오류 메시지에서 가장 네임 스페이스의 자격을 생략했습니다.]

는 비주얼 스튜디오 오류 목록 창에 각 오류의 첫 번째 줄을 (이, 특히 매우 유용한 기능입니다 보여줍니다 . 컴파일러에서 일부 오류 메시지가 오랫동안 상당히 때문에, 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 첫 번째 행의 템플리트는 나머지 행의 템플리트 인수 목록의 순서와 일치합니다.

여기에 문제

StorageFileIStorageFile의 사용을 혼합하는 것입니다.

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

참고이 문제를 해결하면 당신의 람다가 필요하기 때문에, 당신이 오류의 또 다른 쌍을 얻을 것이라는 점 :이 라인의 양쪽에, 당신은 (IStorageFile가 사용되는 경우 라인에서 당근 참조) StorageFile를 사용해야합니다 두 개의 매개 변수를 가짐; 두 번째는 AsyncStatus입니다.

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

내가 WinRT에 대한 짓고 있어요 때문에, 나는 매우 유용 FindFirstFileFindNextFile 기능을 사용할 수 없습니다 : 결국, 그들은 모두로 선언되어야한다.

실제로 Metro 스타일 앱에서 FindFirstFileExFindNextFile을 모두 사용할 수 있습니다. 비 ExFindFirstFile은 사용할 수 없습니다.

비동기식 WinRT 기능은 가능한 한 어디서든지 실용적으로 사용해야하지만, 다른 기능을 사용하지 않는 것은 아닙니다.

+0

왜 우리는'operation'과'status'를 모두 가지고 있을까요? 'operation-> Status'는'status'입니까? – Zingam

4

훨씬 간단한 해결책은 비동기 작업에 PPL을 사용하는 것입니다. 이는 SO 코드 편집기로 작성되었으며, 구문 아니에요 100 %

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

을하지만, PPL이 극적으로 이러한 종류의 코드의 복잡성을 감소하는 방법을 보여줍니다 대신 수동으로 비동기 작업을 롤링의 시도 - 기본적으로 create_task을 사용하여 작업을 만든 다음 작업에 .then 메서드를 사용하여 비동기 완료에 사용되는 람다를 지정합니다.

EDIT : 중첩 된 람다를 제거하도록 업데이트되었습니다.

+0

나는이 구조를 선호한다. 팁 고마워. – Jeff

+1

방금 ​​PPL 전문가 (내 사무실 옆에 있음)와 이야기를 나누었으며 이에 대한 더 나은 형식이 있습니다. 이를 반영하기 위해 내 대답이 업데이트되었습니다. –

+0

신난다. 멋지다. 다시 한번 감사드립니다. 너무 여러 답변을 수락 할 수 없다 ... – Jeff