locked
Return a async action from C++ WinRT component

    Question

  • I'm trying to invoke a C++ WinRT component from Javascript. I've known if I want invoke a async method from C++ WinRT component , I need to wrap this method by using "creat_async" method. My purpose is that press a button then consume a StartRecordAsync method which open a cemare and create a file to store video.

    Here is my code segment in C++:

    IAsyncAction^ Class1::StartRecord() { String^ fileName; fileName = VIDEO_FILE_NAME;

    //here, I create a create_async method, and it's work funciton return a task<StorageFile^> return create_async([this,fileName]->Task<StorageFile^>{ // firstly, I need to create a file, and this progress is async return task<StorageFile^>( ApplicationData::Current->TemporaryFolder->CreateFileAsync(fileName,Windows::Storage::CreationCollisionOption::GenerateUniqueName)) .then([this](task<StorageFile^> fileTask){ this->m_recordStorageFile = fileTask.get(); MediaEncodingProfile^ recordProfile = nullptr; recordProfile = MediaEncodingProfile::CreateMp4(Windows::Media::MediaProperties::VideoEncodingQuality::Auto); // m_capture is a object of MediaCapture class which is already initialized. And I actually want to return this async action, but seemly I didn't do it correctly. return m_capture->StartRecordToStorageFileAsync(recordProfile,this->m_recordStorageFile); }); }); }

    My question is how to return a Async action from another Async method?

    Thanks!

    Wednesday, July 18, 2012 8:37 AM

Answers

  • Hi,

    From the documentation of create_async the return value should be one of 
    the following :-

     

    IAsyncAction^

    IAsyncActionWithProgress<TProgress>^

    IAsyncOperation<TResult>^

    IAsyncOperationWithProgress<TResult, TProgress>^

    So, by wrapping the inner task in inner scope with create_async should so the job. Cn you please elaborate if that does not answer your query.

    -Sagar

    • Proposed as answer by Jesse Jiang Thursday, July 19, 2012 8:25 AM
    • Marked as answer by Jesse Jiang Tuesday, July 24, 2012 8:36 AM
    Wednesday, July 18, 2012 3:00 PM
    Moderator
  • Can you elaborate a bit more on what you're experiencing?

    I wouldn't even expect that snippet to compile with the explicit return specifier "->task<StorageFile^>" on the create_async lambda.  That lambda should be returning a task<void> and not a task<StorageFile^>.  Excepting that, I would expect that it would work (e.g.: the resultant IAsyncAction^ returned from StartRecord does not complete until StartRecordToStorageFileAsync completes).

    There are two tasks in the lambda in question.  For explanation, let's call them t1, and t2:

    auto t1 = task<StorageFile^>(ApplicationData::Current->TemporaryFolder->CreateFileAsync(...))
    
    auto t2 = t1.then([this](task<StorageFile^> fileTask){
        …
        return m_capture->StartRecordToStorageFileAsync(...);
    });
    

    The task t1 should be task<StorageFile^> and t2 should be task<void> as the lambda passed to .then returns an IAsyncAction^ (the result of StartRecordToStorageFileAsync).  When you return this task<void> from the create_async lambda, the result of create_async should be an IAsyncAction^.

    One other aside (regarding the other thread comment): You should never need to nest create_async calls.  It converts tasks to WinRT IAsync* objects for use across a boundary.  It does not add functionality on top of the tasks model.

    • Proposed as answer by Jesse Jiang Thursday, July 19, 2012 8:25 AM
    • Marked as answer by Jesse Jiang Tuesday, July 24, 2012 8:36 AM
    Wednesday, July 18, 2012 11:38 PM

All replies

  • Hi,

    From the documentation of create_async the return value should be one of 
    the following :-

     

    IAsyncAction^

    IAsyncActionWithProgress<TProgress>^

    IAsyncOperation<TResult>^

    IAsyncOperationWithProgress<TResult, TProgress>^

    So, by wrapping the inner task in inner scope with create_async should so the job. Cn you please elaborate if that does not answer your query.

    -Sagar

    • Proposed as answer by Jesse Jiang Thursday, July 19, 2012 8:25 AM
    • Marked as answer by Jesse Jiang Tuesday, July 24, 2012 8:36 AM
    Wednesday, July 18, 2012 3:00 PM
    Moderator
  • Can you elaborate a bit more on what you're experiencing?

    I wouldn't even expect that snippet to compile with the explicit return specifier "->task<StorageFile^>" on the create_async lambda.  That lambda should be returning a task<void> and not a task<StorageFile^>.  Excepting that, I would expect that it would work (e.g.: the resultant IAsyncAction^ returned from StartRecord does not complete until StartRecordToStorageFileAsync completes).

    There are two tasks in the lambda in question.  For explanation, let's call them t1, and t2:

    auto t1 = task<StorageFile^>(ApplicationData::Current->TemporaryFolder->CreateFileAsync(...))
    
    auto t2 = t1.then([this](task<StorageFile^> fileTask){
        …
        return m_capture->StartRecordToStorageFileAsync(...);
    });
    

    The task t1 should be task<StorageFile^> and t2 should be task<void> as the lambda passed to .then returns an IAsyncAction^ (the result of StartRecordToStorageFileAsync).  When you return this task<void> from the create_async lambda, the result of create_async should be an IAsyncAction^.

    One other aside (regarding the other thread comment): You should never need to nest create_async calls.  It converts tasks to WinRT IAsync* objects for use across a boundary.  It does not add functionality on top of the tasks model.

    • Proposed as answer by Jesse Jiang Thursday, July 19, 2012 8:25 AM
    • Marked as answer by Jesse Jiang Tuesday, July 24, 2012 8:36 AM
    Wednesday, July 18, 2012 11:38 PM