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
thenreturns you a new task. So the lastthenin 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 callthenon it.Secondly, keep in mind that your function is returning a
task, not the stream itself. Usually you'd have the lastthenin 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_taskrather 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_asyncif you instead want to return anIAsyncInfoderivative.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_taskand 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
thento 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_allorwhen_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.