返回PPL任务的c++函数签名
C++ Function signature that returns a PPL task?
当涉及到在c++环境中使用PPL任务时,我是一个完全的新手,所以我很难弄清楚下面c#代码的c++语法是什么:
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;
}
这段c#代码取自Windows Store的反向微软示例代码。到目前为止,我能得到的最好的是:
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?
}
但是它会生成以下编译错误:
error C4716: 'GetImageStream' : must return a value
我明白为什么会发生这个错误,但我不知道我怎么能有一个函数,返回一个任务没有返回值在两个不同的位置?我甚至还没有解决GetImageStream。
我甚至不确定我选择了正确的道路…
谢谢!
你真的很接近了。您可能忽略了一个关键点,即then
返回给您一个新任务。因此,链中的最后一个then
决定了您的任务类型。
auto t = task<int>([] { return 0; });
// t is task<int>
auto t = task<int>([] { return 0; })
.then([](int i) { return 3.14; });
// t is task<double>
auto t = task<int>([] { return 0; })
.then([](int i) { return 3.14; })
.then([](double d) { return "foo"; });
// t is task<const char*>
如果你只看第一行,看起来你总是有一个task<int>
,但是你可以看到,如果你立即调用then
,情况不一定是这样。
其次,记住你的函数返回的是一个task
,而不是流本身。通常,您会让链中的最后一个then
返回您将从函数返回的任务,而不是将任务存储在局部变量中,您只需返回它。例如:
task<const char*>
get_foo()
{
return task<int>([] { return 0; })
.then([](int i) { return 3.14; })
.then([](double d) { return "foo"; });
}
再次,它看起来有点奇怪,因为快速浏览会让您认为返回的是task<int>
。通过使用create_task
而不是显式调用任务构造函数,可以很好地处理这个问题。它使您完全不必显式地指定任务的类型。此外,如果您想返回IAsyncInfo
的衍生物,则很容易将其更改为create_async
。
我对BitmapEncoder
一点也不熟悉,但这里有一个调整版本的代码,可能会奏效:
Concurrency::task<IRandomAccessStream^> GetImageStream()
{
auto stream = ref new InMemoryRandomAccessStream();
return create_task(BitmapEncoder::CreateAsync(BitmapEncoder::JpegEncoderId, stream))
.then([this, width, height, imageBytes](BitmapEncoder^ encoder)
{
// are width, height, and imageBytes member variables?
// if so, you should only need to capture them OR "this", not both
encoder->SetPixelData(BitmapPixelFormat::Rgba8, BitmapAlphaMode::Ignore, width, height, 96.0, 96.0, imageBytes);
return encoder->FlushAsync();
}).then([stream]()
{
// this should work fine since "stream" is a ref-counted variable
// this lambda will keep a reference alive until it uses it
return stream;
});
}
唯一真正的变化是使用create_task
并立即返回其结果。
我自己还在学习PPL,但我学到的一件事是,到目前为止,你应该总是做一些与你创建的任何任务。通常要做的事情是使用then
将其转换为新的/不同的任务,但您仍然需要对最后一个then
返回的任务做一些事情。通常你只是返回它,如上所述。有时,您会将其添加到任务容器中,然后将其与when_all
或when_any
分组在一起。有时您只需自己调用get()
来等待其结果。但关键是,如果你创建了一个任务,但没有对它做任何事情,那么很可能是哪里出了问题。
如果有人关心,这里是如何实现上面提到的GetImageStreamRef,在c++版本:
task<RandomAccessStreamReference^> GetImageStreamRef()
{
return GetImageStream().then([](IRandomAccessStream^ pStream)
{
return RandomAccessStreamReference::CreateFromStream(pStream);
});
}
另外,确保永远不要在任何这些任务上使用。get(),否则你会得到一个异常抛出,说"在Windows运行时STA中等待任务是非法的"。获取该图像流引用值的正确方法是,例如,在DataRequestHandler上设置DataRequest上的位图数据:
void OnBitmapRequested(DataProviderRequest^ request)
{
auto Deferral = request->GetDeferral();
GetImageStreamRef().then([Deferral, request](RandomAccessStreamReference^ pStreamRef)
{
try
{
request->SetData(pStreamRef);
Deferral->Complete();
}
catch( std::exception ex )
{
Deferral->Complete();
throw ex; //Propagate the exception up again
}
});
}
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 将对象数组的引用传递给函数
- 函数调用中参数的顺序重要吗
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用不带参数的函数访问结构元素
- 代码在main()中运行,但在函数中出现错误
- 内置函数可查看CPP中的成员变量
- 如何获取std::result_of函数的返回类型
- 如何在c++中为模板函数实例创建快捷方式
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗