首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在C++/Cli中使用`__await`等待第三方物流任务

在C++/Cli中使用`__await`等待第三方物流任务
EN

Stack Overflow用户
提问于 2016-06-28 12:05:59
回答 1查看 1.4K关注 0票数 2

我发现我可以使用Visual 2015中的关键字__resumable__await来做一些与C#的async/ C++中的await非常相似的事情。

现在我想知道是否有一种在C++/Cli中使用__await来执行TPL任务的方法?

EN

回答 1

Stack Overflow用户

发布于 2019-07-28 06:38:28

有三个主要障碍:

  1. 如果您试图在用/clr编译的项目中包含ppl头,您将得到一个错误,因为有些C++头仍然禁止在C++-CLI项目中使用。其中包括<mutex><condition_variable><future> (尽管<mutex>似乎适合于VisualStudio2019)。通过使用原始的WinAPI结构实现自己的库,我克服了这个限制。但我想这有点极端。或者,您可以转发声明所有禁止的类型(但您必须在任何地方使用另一个级别的间接方向)
  2. 为了使用await / co_await,必须使用/await标志编译C++模块,这是不允许使用/clr标志的。
  3. 调用co_await的函数的返回类型必须实现特定的概念(基本上,编译器在使用co_await时内部调用的一组函数)。您不能像在C#中那样使用空返回值,其他托管返回值也没有意义。

我发现唯一起作用的东西(一旦我克服了限制1)是将本机awaitable类型(您自己实现的未来/任务)转换为托管Task^,可以在C#代码中等待。

代码语言:javascript
运行
复制
template <typename NativeResultPolicy, typename NativeCallableT, typename... Args>
Task<typename NativeResultPolicy::ManagedResultT>^
    MethodAsTask(NativeCallableT nativeMethod, typename ClassOf<decltype(nativeMethod)>::type* self, Args&&... args)
{
   // prepare a completion source and invoke native method
   gcroot<TaskCompletionSource<NativeResultPolicy::ManagedResultT>^> taskCompletionSrc= gcnew TaskCompletionSource<NativeResultPolicy::ManagedResultT>();    
    (*self.*nativeMethod)(std::forward<Args>(args)...).then(
        [taskCompletionSrc](NThreading::srfuture<typename NativeResultPolicy::NativeResultT> fut)
    {
        // once future is ready, translate its contained value / exception to a managed value / exception using the supplied policy.
        NativeResultPolicy::SetCompletionSource(taskCompletionSrc, fut);
    }
    );
    // return a Task^ that can be awaited
    return completionTask->Task;
}

上面的转换函数调用一个返回本机任务类对象的方法,并使用::then和lambda表达式在任务完成后为TaskCompletionSource设置值。

NativeResultPolicy类型是一个简单的类型,它有一个执行实际转换的方法。以下是一个例子:

代码语言:javascript
运行
复制
class CompletionPolicy
{
public:
    using NativeResultT = typename void;
    using ManagedResultT = bool;

    static void SetCompletionSource(TaskCompletionSource<ManagedResultT>^ completionResult, future_t<NativeResultT>& fut)
    {
        try
        {
            fut.get();
            completionResult->SetResult(static_cast<bool>(true));
        }
        catch (const std::exception& err)
        {
            completionResult->SetException(gcnew System::IO::IOException(gcnew System::String(err.what())));
        }
    }
};
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38075786

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档