如何在c++/cx中从嵌套任务返回值

How to return value from nested task in c++/cx?

本文关键字:嵌套 任务 返回值 cx c++      更新时间:2023-10-16

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

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

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

create_task(...).then(...).then(...)创建的任务(或值)设置为return

如果你需要同步获得结果,你可以尝试task上调用.get(),但是而不是在你的应用程序的主UI线程上工作,并且不是你应该做的事情。代码今天可能在后台线程中工作,但是将来你可能会在UI线程中调用这个函数——也许是通过一些非常迂回的方式——然后你的应用程序会崩溃。修复应用程序的唯一方法是重新设计你的代码,使其异步…就像一开始就应该那样。

另外,请注意,尝试做自己的工作来同步获取值(比如在任务中调用对象的WaitForSingleObjectEx())可能会导致许多WinRT异步方法的UI线程死锁。别这样!

您应该继续异步链来处理该值。这里有一个简单的例子;从主UI线程调用test()

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.rn", 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.rn",
      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.rn",
      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.rn",
      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.