我需要在我声明的方法中调用Async方法。该方法应返回一个值。我正在尝试将对Windows应用商店的调用包装成一个易于使用的类。我的方法应如下所示:
bool Purchase(enum_InAppOption optionToPurchase);
enum_InAppOption
是一个包含要购买的所有应用内选项的枚举。在某些时候,我需要致电RequestProductPurchaseAsync
。此调用的结果确定方法是否应返回true
或false
。我是c ++ / cx的新手(或者至少我从现在到最后一次使用c ++之间有很长的历史),所以也许这比我想象的要容易。
create_task
看起来像这样:
create_task(CurrentAppSimulator::RequestProductPurchaseAsync(this->_LastProductId, false))
我考虑/尝试的选项:
返回任务不会抽象商店
试图调用等待任务。我有异常An invalid parameter was passed to a function that considers invalid parameters fatal.
尝试使用structured_task_group
,但似乎这不允许非void返回方法或我试图提供错误的解释。编译器返回错误C2064(已谷歌搜索,但我无法得到要改变的地方)
使用一系列任务和when_all
在页面中间的http://msdn.microsoft.com/en-us/library/dd492427.aspx#when_all上找到以下代码:
array<task<void>, 3> tasks =
{
create_task([] { wcout << L"Hello from taskA." << endl; }),
create_task([] { wcout << L"Hello from taskB." << endl; }),
create_task([] { wcout << L"Hello from taskC." << endl; })
};
auto joinTask = when_all(begin(tasks), end(tasks));
// Print a message from the joining thread.
wcout << L"Hello from the joining thread." << endl;
// Wait for the tasks to finish.
joinTask.wait();
所以我尝试将其翻译成以下代码:
array<task<Platform::String^>,1> tasks = {
create_task(CurrentAppSimulator::RequestProductPurchaseAsync(this->_LastProductId, false))
};
即使我包含编译器抛出C2065('array':未声明的标识符),C2275('Concurrency :: task&lt; _ReturnType&gt;':非法使用此类型作为表达式和一些似乎是错误跟踪的错误在那两个。
总结:如何在异步任务完成后使方法返回,这样我就能根据异步进行的事情返回一个有意义的结果?
答案 0 :(得分:2)
如何在异步任务完成后使方法返回,这样我就能根据异步进行的事情返回一个有意义的结果?
这没有多大意义:如果你想在返回之前等待它完成,那么“stuff”不是异步。这是同步的定义。
使用C ++ / CX时,您无法等待STA上尚未完成的任务。任何这样做的尝试都会导致异常被抛出。如果要在STA上调用Purchase()
并且它是否启动异步操作,则在返回之前不能等待该操作完成。
相反,您可以在异步操作完成时使用.then
执行另一个操作。如果需要在调用线程上执行continuation,请确保传递use_current()
continuation上下文以确保在正确的上下文中执行continuation。
答案 1 :(得分:1)
的Sascha,
正如@James正确提到的那样,你不能在UI线程中等待,然后你会让应用程序无响应,有不同的方法可以避免等待:
concurrency::task::then
; 您不能在UI线程中等待,但您可以等待UI线程上的操作完成,这意味着您可以在task_completion_event中包装在UI上运行的任务的未来结果然后在另一个(后台)线程中等待事件并处理结果;
concurrency::task_completion_event<Platform::String^> purchaseCompleted;
create_task(CurrentAppSimulator::RequestProductPurchaseAsync(
this->_LastProductId, false)).then(
[purchaseCompleted](concurrency::task<Platform::String^> task)
{
try
{
purchaseCompleted.set(task.get());
}
catch(Platform::Exception^ exception)
{
purchaseCompleted.set_exception(exception);
}
});
// and somewhere on non-UI thread you can do
Platform::String^ purchaseResult = create_task(purchaseCompleted).get();
您可以使用更多特定于WinRT的工具而不是并发运行时实现上一个技巧,更确切地说,IAsyncOperation<T>
::Completed
和IAsyncOperation<T>::GetResults
;
和