create_task和返回值

时间:2012-10-06 08:03:25

标签: c++ windows-8 c++-cx windows-store

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

bool Purchase(enum_InAppOption optionToPurchase);

enum_InAppOption是一个包含要购买的所有应用内选项的枚举。在某些时候,我需要致电RequestProductPurchaseAsync。此调用的结果确定方法是否应返回truefalse。我是c ++ / cx的新手(或者至少我从现在到最后一次使用c ++之间有很长的历史),所以也许这比我想象的要容易。

create_task看起来像这样:

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

我考虑/尝试的选项:

  1. 返回任务不会抽象商店

  2. 试图调用等待任务。我有异常An invalid parameter was passed to a function that considers invalid parameters fatal.

  3. 尝试使用structured_task_group,但似乎这不允许非void返回方法或我试图提供错误的解释。编译器返回错误C2064(已谷歌搜索,但我无法得到要改变的地方)

  4. 使用一系列任务和when_all

  5. 在页面中间的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;':非法使用此类型作为表达式和一些似乎是错误跟踪的错误在那两个。

    总结:如何在异步任务完成后使方法返回,这样我就能根据异步进行的事情返回一个有意义的结果?

2 个答案:

答案 0 :(得分:2)

  

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

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

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

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

答案 1 :(得分:1)

的Sascha,

  1. 返回任务会抽象出商店,我认为这是最合理的决定,因为你不是要限制助手类的用户直接得到结果,而是允许他们处理结果他们自己的方式和异步。
  2. 正如@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> ::CompletedIAsyncOperation<T>::GetResults;

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