create_task并返回值

create_task and return values

本文关键字:返回值 task create      更新时间:2023-10-16

我需要在我声明的方法中调用Async方法。该方法应返回一个值。我正在尝试将对Windows应用商店的调用包装成一个易于使用的类。我的方法应该是这样的:

bool Purchase(enum_InAppOption optionToPurchase);

enum_InAppOption是一个枚举,包含要购买的所有应用内选项。在某个时刻,我需要调用RequestProductPurchaseAsync。此调用的结果确定该方法应该返回true还是false。我是c++/cx的新手(或者至少从现在到上次使用c++,我有很长的历史),所以也许这比我想象的更容易。

create_task看起来像这样:

create_task(CurrentAppSimulator::RequestProductPurchaseAsync(this->_LastProductId, false))

我考虑过/尝试过的选项:

  1. 返回任务不会抽象存储

  2. 尝试调用wait处理任务。我有异常An invalid parameter was passed to a function that considers invalid parameters fatal.

  3. 尝试使用structured_task_group,但这似乎不允许使用非void返回方法,或者我试图提供错误的解释。编译器返回错误C2064(已在谷歌上搜索,但我不知道该更改什么)

  4. 使用任务阵列和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("concurrent::task<_ReturnType>':非法使用此类型作为表达式,以及一些似乎是这两个之后的错误的错误。

综上所述:如何在异步任务完成后让方法返回,这样我就可以根据异步进行的事情返回一个有意义的结果?

如何在异步任务完成后让方法返回,这样我就可以根据异步进行的事情返回有意义的结果?

这没有多大意义:如果你想在返回之前等待它完成,那么"东西"就不是异步的。这就是同步的定义。

使用C++/CX时,不能在STA上等待尚未完成的任务。任何这样做的尝试都将导致抛出异常。如果要在STA上调用Purchase(),并且它启动了异步操作,则不能等待该操作完成后再返回。

相反,当异步操作完成时,可以使用.then执行另一个操作。如果需要在调用线程上执行延续,请确保传递use_current()延续上下文,以确保在正确的上下文中执行延续。

Sascha,

  1. 返回一个任务将抽象出存储,我认为这将是最合理的决定,因为你没有限制助手类的用户直接获得结果,而是允许他们以自己的方式异步处理结果
  2. 正如@James正确提到的,你不允许在UI线程中等待,然后你会让应用程序没有响应,有不同的方法可以避免等待:

    • 使用concurrency::task::then创建一个延续
    • 你不能在UI线程中等待,但你可以等待UI线程上的操作完成,这意味着你可以将UI上运行的任务的未来结果包装在task_completion_event中,然后在另一个(后台)线程中等待事件并处理结果;

      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>::CompletedIAsyncOperation<T>::GetResults来实现前面的技巧;

  3. 在这里似乎无关紧要,因为你只有一个真正的任务,那就是购买