c++ - 如何从 C++/cx 中的嵌套任务返回值?

标签 c++ multithreading visual-c++ win-universal-app c++-cx

我有一堆像这样的线程任务:

create_task(somewinrtasyncfunction()).then([this(variable_that_the_last_task_returned)
{
    //task here
    return info;
}).then([this](info)
{
    //another task here
    return status});

现在我想在任务之外的调用它的函数中使用status。我如何访问它?

最佳答案

return create_task(...).then(...).then(...) 创建的任务(或值) 。

如果需要同步获取结果,可以尝试调用.get()关于task但是这将无法在应用程序的主 UI 线程上工作,并且不是您应该做的事情。今天的代码可能在后台线程上运行,但将来您可能最终会在 UI 线程上调用该函数(也许是通过某种非常迂回的方式),然后您的应用程序就会崩溃。修复应用程序的唯一方法是将您的代码重新设计为异步......就像它本来应该放在首位的那样。

另请注意,尝试自行解决方法以同步获取值(例如对任务中发出信号的对象调用 WaitForSingleObjectEx())可能会导致许多 WinRT 异步方法的 UI 线程死锁。 不要这样做!

您应该继续异步链以对值进行操作。这是一个简单的例子;调用test()来自您的主 UI 线程。

concurrency::task<int> get_double_async(int value)
{
  return concurrency::create_task(
    [value]()
  {
    return value * 2;
  });
}

// DON'T DO THIS - IT IS A BUG FARM WAITING TO HAPPEN!
int try_calling_get()
{
  auto value = 2;
  value = get_double_async(value).get(); // TODO: Don't do this!
  value = get_double_async(value).get(); // TODO: Don't do this!
  return value;
}

concurrency::task<int> do_it_properly()
{
  auto value = 2;
  return get_double_async(value).then([](int value)
  {
    return get_double_async(value).then([](int value)
    {
      return value;
    });
  });
}

void test()
{
  wchar_t buff[255];
  swprintf_s(buff, L"test() being called on thread %d.\r\n", GetCurrentThreadId());
  OutputDebugString(buff);

  // this will fail at runtime if called from UI thread
  try
  {
    auto x = try_calling_get();
  }
  catch (const concurrency::invalid_operation& op)
  {
    // "Illegal to wait on a task in a Windows Runtime STA"
    swprintf_s(buff, L"try_calling_get() threw '%hs'; thread is %d.\r\n",
      op.what(), GetCurrentThreadId());
    OutputDebugString(buff);
  }

  // this will "work", but only because it is forced into a threadpool thread
  concurrency::create_task([]
  {
    auto x = try_calling_get(); // TODO: Don't do this!
    wchar_t buff[255];
    swprintf_s(buff, L"try_calling_get() returned %d; thread is %d.\r\n",
      x, GetCurrentThreadId());
    OutputDebugString(buff);
  });

  // this is the preferred way to do it
  do_it_properly().then([](int x)
  {
    wchar_t buff[255];
    swprintf_s(buff, L"do_it_properly() returned %d; thread is %d.\r\n",
      x, GetCurrentThreadId());
    OutputDebugString(buff);
  });
}

请注意,此示例使用基于值的延续 .then([](int value){...})而不是基于任务的延续.then([](task<int> value){...}) ;如果您想控制异常等事情,您可以使用基于任务的延续。

这是一个示例运行(线程ID每次都会不同,有时最后两个会相同)

test() being called on thread 3576.
First-chance exception at 0x77134598 in UniversalNativeApp.Windows.exe: Microsoft C++ exception: Concurrency::invalid_operation at memory location 0x038CEC94.
try_calling_get() threw 'Illegal to wait on a task in a Windows Runtime STA'; thread is 3576.
try_calling_get() returned 8; thread is 5972.
do_it_properly() returned 8; thread is 9976.

关于c++ - 如何从 C++/cx 中的嵌套任务返回值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33323277/

相关文章:

c++ - 从点云中检测一组平面

java - java线程之间共享变量的方法

c++ - 有一个dll项目,我可以强制将它链接到一个静态库吗?

visual-studio - 让 PC-lint 与 Visual Studio 一起使用

c++ - 刷新缓冲区是什么意思?

c++ - 斧头错误 : You cannot access the cpp package while targeting cross (for cpp. 库)

java - midlet 的线程安全检查变量

python threading.Timer : do i need to protect the variable accessed inside the callback?

c++ - PostMessage 不会触发 Message Handler

c++ - Opengl 和旋转的奇怪问题。有没有人见过这个?