0

I am new to WinRT c++. I am trying to pass an StorageFile image from C# and open the file and set it as source in BitmapImage in WinRT to extract height and width of image. I am using the following code.

auto openOperation = StorageImageFile->OpenAsync(FileAccessMode::Read); // from http://msdn.microsoft.com/en-us/library/windows/desktop/hh780393%28v=vs.85%29.aspx
openOperation->Completed = ref new
    AsyncOperationCompletedHandler<IRandomAccessStream^>(
    [=](IAsyncOperation<IRandomAccessStream^> ^operation, AsyncStatus status)
{
    auto Imagestream = operation->GetResults(); 
    BitmapImage^ bmp = ref new BitmapImage();
    auto bmpOp = bmp->SetSourceAsync(Imagestream);
    bmpOp->Completed = ref new 
        AsyncActionCompletedHandler (
        [=](IAsyncAction^ action, AsyncStatus status)
    {
        action->GetResults();
        UINT32 imageWidth = (UINT32)bmp->PixelWidth;
        UINT32 imageHeight = (UINT32)bmp->PixelHeight;
    });
});

This code does not seem to work. after the line BitmapImage^ bmp = ref new BitmapImage(); the debugger stops saying no source code is found. Can you help me write the correct code?

Filip Skakun
  • 31,347
  • 6
  • 71
  • 99
croc
  • 231
  • 3
  • 12
  • I think you meant to write `openOperation->Completed` **`+=`** `ref new...` and `bmpOp->Completed` **`+=`** `ref new...` – Filip Skakun Sep 19 '14 at 15:28

1 Answers1

1

I think you meant to write openOperation->Completed += ref new... and bmpOp->Completed += ref new.... I'm not an expert in C++, but from what I have seen - async operations are typically wrapped in create_task calls. Not really sure why - maybe to avoid subscribing to events without unsubscribing?

I think it should look roughly like this:

auto bmp = ref new BitmapImage();

create_task(storageImageFile->OpenAsync(FileAccessMode::Read)) // get the stream
    .then([bmp](IRandomAccessStream^ ^stream) // continuation lambda
{
    return create_task(bmp->SetSourceAsync(stream)); // needs to run on ASTA/Dispatcher thread
}, task_continuation_context::use_current()) // run on ASTA/Dispatcher thread
    .then([bmp]() // continuation lambda
{
        UINT32 imageWidth = (UINT32)bmp->PixelWidth; // needs to run on ASTA/Dispatcher thread
        UINT32 imageHeight = (UINT32)bmp->PixelHeight; // needs to run on ASTA/Dispatcher thread

        // TODO: use imageWidth and imageHeight
}, task_continuation_context::use_current()); // run on ASTA/Dispatcher thread
Filip Skakun
  • 31,347
  • 6
  • 71
  • 99
  • Thanks a lot. I have very little understanding of ppl task and concunrrency tasks. Just for a little advice i should use create_task() when the async function returns IAsyncOperation and use task_continuation_context::use_current() to capture return value when the async function returns IAsyncAction. Is that right? – croc Sep 22 '14 at 10:11
  • `create_task` wraps `IAsyncOperation` in a task you can continue. `.then(lambda, task_continuation_context::use_current())` makes the lambda run on the UI thread which is required when you touch UI objects. – Filip Skakun Sep 22 '14 at 14:44