.net 在C+中使用`u wait`等待第三方物流任务+/Cli < >我发现在Visual Studio 2015中,我可以使用关键字 >恢复> >代码>等待/,以类似于C++的代码 >代码>在C++中等待< />代码>

.net 在C+中使用`u wait`等待第三方物流任务+/Cli < >我发现在Visual Studio 2015中,我可以使用关键字 >恢复> >代码>等待/,以类似于C++的代码 >代码>在C++中等待< />代码> ,.net,visual-studio,async-await,c++-cli,.net,Visual Studio,Async Await,C++ Cli,现在我想知道是否有一种方法可以在C++/Cli中使用\uuu wait执行TPL任务?有三个主要障碍: LI>如果您尝试将PPL头包含在用CL/CLR编译的项目中,您将得到一个错误,因为在C++ +CLI项目中仍然有一些C++标题被禁止使用。例如,包括和(尽管似乎适合Visual Studio 2019)。 通过使用原始WinAPI构造实现自己的库,我克服了这个限制。但我想这有点极端。或者,您可以向前声明所有禁止的类型(但您必须在任何地方使用另一个间接级别) LI>为了使用等待 >代码> C

现在我想知道是否有一种方法可以在C++/Cli中使用
\uuu wait
执行TPL任务?

有三个主要障碍:

<> LI>如果您尝试将PPL头包含在用CL/CLR编译的项目中,您将得到一个错误,因为在C++ +CLI项目中仍然有一些C++标题被禁止使用。例如,包括
(尽管
似乎适合Visual Studio 2019)。 通过使用原始WinAPI构造实现自己的库,我克服了这个限制。但我想这有点极端。或者,您可以向前声明所有禁止的类型(但您必须在任何地方使用另一个间接级别) <> LI>为了使用<代码>等待<代码> >代码> COEAWAUE > C++模块必须用/CLAL标志不允许的/AWAN标志编译。< /LI>
  • 调用
    co_wait
    的函数的返回类型必须实现某个概念(基本上,当您使用
    co_wait
    时,编译器在内部调用一组函数)。例如,不能像在C中那样使用void返回值,其他托管返回值也没有意义
  • 我发现唯一可行的方法(一旦我克服了限制1)是将本机等待类型(您自己实现的未来/任务)转换为托管的
    task^
    ,可以在C#code中等待


    你好,尼娜。有趣的解决方案。我读了好几遍,但我想我现在明白发生了什么。您正在将未来转换为第三方物流任务,以便在C#中将其作为可等待的任务使用。例如,您希望在C#项目中使用C++/Cli模块。我试图实现完全相反的事情:在C++项目中,我如何才能消耗一个可期待的任务(来自C语言库)。正如我在3年前提出的这个问题,在任何C++编译器中都没有协同程序。但是既然你说/await标志与/clr不兼容,那么协同程序也帮不了我,对吧?对。c++-cli中根本不支持异步/等待。这意味着你必须使用原始回调实现所有的东西。如果我记得正确的话,也很痛苦,因为C++ LAMBDAS与.NET委托不兼容。我认为c++-cli的全部目的是向高级托管代码公开本机功能,而不是相反。我不同意这一点。Microsoft::VisualC::MFC::CWInformControl或
    System::Windows::Interop::HwndSource
    等类型使人们能够将Winforms或WPF控件嵌入Win32/C++应用程序。从这里开始,将所有类型的.NET库链接到这些应用程序只是一小步。在大多数情况下,它的工作非常出色。看起来C++/Cli已经过了最好的日子。
    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;
    }
    
    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())));
            }
        }
    };