【问题标题】:create_task and return valuescreate_task 和返回值
【发布时间】:2012-09-27 07:12:38
【问题描述】:

我需要在我声明的方法中调用 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(已用 Google 搜索,但我无法理解要更改的内容)

  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': undeclared identifier), C2275 ('Concurrency::task<_returntype>': 非法使用这种类型作为表达式和一些错误似乎是后续错误关于那两个。

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

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

    【讨论】:

      【解决方案2】:

      萨沙,

      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&lt;T&gt;::CompletedIAsyncOperation&lt;T&gt;::GetResults

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-24
        • 2014-12-13
        相关资源
        最近更新 更多