I am a total noob when it comes to using PPL tasks within the C++ environment, so I am having a hard time to figure out what would be the C++ syntax of the following C# code:
private static async Task<RandomAccessStreamReference> GetImageStreamRef()
{
return RandomAccessStreamReference.CreateFromStream(await GetImageStream());
}
private static async Task<IRandomAccessStream> GetImageStream()
{
var stream = new InMemoryRandomAccessStream();
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.BmpEncoderId, stream);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, width, height, 96, 96, imageBytes);
await encoder.FlushAsync();
return stream;
}
This C# code was taken from the Windows Store reversi Microsoft sample code. The best I could get so far is this:
Concurrency::task<IRandomAccessStream^> GetImageStream()
{
auto stream = ref new InMemoryRandomAccessStream();
task<BitmapEncoder^>(BitmapEncoder::CreateAsync(BitmapEncoder::JpegEncoderId, Stream)).then([this, stream, width, height, imageBytes](BitmapEncoder^ encoder)
{
encoder->SetPixelData(BitmapPixelFormat::Rgba8, BitmapAlphaMode::Ignore, width, height, 96.0, 96.0, imageBytes);
return encoder->FlushAsync();
}).then([this, stream]()
{
return stream; //Does this even make sense?
});
//return stream; //Not sure if I should have this here?
}
But it generates the following compile error:
error C4716: 'GetImageStream' : must return a value
I understand why this error happens, but I have no clue how I can have a function that returns a task without having a return value at two different locations? I haven't even tackled GetImageStream yet.
I am not even sure I took the right path into this...
Thank you!
You're real close. A key point you might be missing is that
then
returns you a new task. So the lastthen
in the chain determines the type of your task.If you just glance at the first line, it looks like you've always got a
task<int>
, but as you can see that's not necessarily the case if you immediately callthen
on it.Secondly, keep in mind that your function is returning a
task
, not the stream itself. Usually you'd have the lastthen
in your chain return you the task that you'll return from your function, and rather than store the task in a local variable, you just return it. For example:Again, it looks a tad strange because a quick glance makes you think that you're returning a
task<int>
. This is nicely handled by usingcreate_task
rather than calling the task constructor explicitly. It frees you from having to explicitly specify the task's type at all. Additionally, it's easily changed tocreate_async
if you instead want to return anIAsyncInfo
derivative.I'm not at all familiar with
BitmapEncoder
, but here's a tweaked version of your code that might do the trick:The only real change is using
create_task
and immediately returning its result.I'm still learning PPL myself, but one thing I've learned that's held up so far is that you should pretty much always be doing something with any task you create. The usual thing to do is use
then
to turn it into a new/different task, but you still need to do something with the task returned by the lastthen
. Oftentimes you just return it, as above. Sometimes you'll add it to a container of tasks which are then grouped together withwhen_all
orwhen_any
. Sometimes you'll just callget()
on it yourself to wait for its result. But the point is that if you create a task and don't do anything with it, then there's probably something wrong.