C++ cli 在C++/CLI中创建System::Threading::Tasks时发生编译错误。无法发现错误 我试图让一个C++或CLI包装层调用非托管C++ DLL,它将把任务返回给C层的函数公开。非托管函数非常昂贵,这就是我想要异步版本的原因

C++ cli 在C++/CLI中创建System::Threading::Tasks时发生编译错误。无法发现错误 我试图让一个C++或CLI包装层调用非托管C++ DLL,它将把任务返回给C层的函数公开。非托管函数非常昂贵,这就是我想要异步版本的原因,c++-cli,task-parallel-library,C++ Cli,Task Parallel Library,但我无法建造它 我的方法是在C++/CLI中使用TaskFactory::StartNew提供System::Func 它接受一个参数并返回一个值。MSDN中的原型如下所示: StartNew<TResult>(Func<Object,TResult>, Object) 如果我想让我创建的任务将参数传递到昂贵的同步函数中,那么我必须使用它。我使对象包含我需要的所有参数,并封装到某个内部类中。我的代码可以解包并使用它们 下面是一个简单的C++/CLI示例,我试图用它来说明

但我无法建造它

我的方法是在C++/CLI中使用TaskFactory::StartNew提供System::Func 它接受一个参数并返回一个值。MSDN中的原型如下所示:

StartNew<TResult>(Func<Object,TResult>, Object)
如果我想让我创建的任务将参数传递到昂贵的同步函数中,那么我必须使用它。我使对象包含我需要的所有参数,并封装到某个内部类中。我的代码可以解包并使用它们

下面是一个简单的C++/CLI示例,我试图用它来说明这个问题。下面是我得到的错误。我已清楚地识别出故障线路,该线路出现故障。在VisualStudio中还有另一行显示为红色,但不会导致编译器错误

这些代码都在VS 2017中

using namespace System;
using namespace System::Threading;
using namespace System::Threading::Tasks;

namespace CppCliLayer
{
// Arguments class.  Because TaskFactory.StartNew only appears to allow us one
// argument to our task function, at best (a System::Object).  This packs up the
// multiple arguments we'll need

public ref class Arguments
{
    String^ string;
    int     intVal;
public:
    Arguments(String^ s, int n) { string = s; intVal = n; }

    property String^  Text  { String^ get() { return string; } }
    property int      Token { int     get() { return intVal; } }
};

// "Expensive": Want to return an instance of this from a long running task..
public ref class Expensive
{
public:
    static Expensive^ CreateExpensively(Arguments^)
    {
        // Do slow stuff with arguments, then create. 
        // <Imagine slow synchronous code here....>

        return gcnew Expensive();
    }
};

// Function that takes a long time to create an instance of Expensive

Task<Expensive^>^ ExpensivelyCreateAsync(String^ s, int n)
{
    auto func = gcnew Func<Arguments^, Expensive^>(&Expensive::CreateExpensively);  // *** VS UNDERLINES THIS WITH A SQUIGGLY (see below for more)
    auto args = gcnew Arguments(s, n);
    return TaskFactory::StartNew<Expensive^>(func, args);  // *** THIS LINE FAILS
}

}
错误呢

1>------ Build started: Project: CppCliLayer, Configuration: Debug x64 ------
1>testcli.cpp
1>d:\dev\testcli.cpp(130): error C2665: 'System::Threading::Tasks::TaskFactory::StartNew': none of the 3 overloads could convert all the argument types
1>d:\dev\testcli.cpp(130): note: could be 'System::Threading::Tasks::Task<CppCliLayer::Expensive ^> ^System::Threading::Tasks::TaskFactory::StartNew<CppCliLayer::Expensive^>(System::Func<System::Object ^,CppCliLayer::Expensive ^> ^,System::Object ^)'
1>d:\dev\testcli.cpp(130): note: or       'System::Threading::Tasks::Task<CppCliLayer::Expensive ^> ^System::Threading::Tasks::TaskFactory::StartNew<CppCliLayer::Expensive^>(System::Func<CppCliLayer::Expensive ^> ^,System::Threading::Tasks::TaskCreationOptions)'
1>d:\dev\testcli.cpp(130): note: or       'System::Threading::Tasks::Task<CppCliLayer::Expensive ^> ^System::Threading::Tasks::TaskFactory::StartNew<CppCliLayer::Expensive^>(System::Func<CppCliLayer::Expensive ^> ^,System::Threading::CancellationToken)'
1>d:\dev\testcli.cpp(130): note: while trying to match the argument list '(System::Func<CppCliLayer::Arguments ^,CppCliLayer::Expensive ^> ^, CppCliLayer::Arguments ^)'
1>Done building project "testcli_v15.vcxproj" -- FAILED.
StopOnFirstBuildError: Build cancelled because project "corecli_v15" failed to build.
Build has been canceled.
我应该提到,我的C++/CLI dll的目标是.NET Framework 4.6.2 我还应该提到,编译器在这一行下面加了一条红色的曲线

auto func = gcnew Func<Arguments^, Expensive^>(&Expensive::CreateExpensively);
当我将鼠标悬停在它上面时,它给我的消息应该是一个类型说明符。但它不会生成编译错误

有人知道我做错了什么吗?

异步函数CreateExpensively只能接受对象作为参数,不能接受参数等其他对象。您可以将参数强制转换为CreateExpensive中的对象。 创建TaskFactory的新实例,而不是使用TaskFactory::StartNew。 我认为红色的波形是一个intellisense解析器错误,我在我的VS2017中也看到了它。 工作代码如下:

// "Expensive": Want to return an instance of this from a long running task..
public ref class Expensive
{
public:
    static Expensive^ CreateExpensively(Object^ argObj)
    {
        Arguments^ args = (Arguments^) argObj;  // you can pass it Arguments here
        // Do slow stuff with arguments, then create. 
        // <Imagine slow synchronous code here....>

        return gcnew Expensive();
    }

    Task<Expensive^>^ ExpensivelyCreateAsync(String^ s, int n)
    {
        auto func = gcnew Func<Object^, Expensive^>(&Expensive::CreateExpensively);
        Arguments^ args = gcnew Arguments(s, n);

        // Use Task instead of StartNew
        Task<Expensive^>^ asyncTask = gcnew Task<Expensive^>(func, args);
        asyncTask->Start();
        return asyncTask;
    }
};
异步函数CreateExpensively函数只能接受对象作为参数,不能接受参数等其他对象。您可以将参数强制转换为CreateExpensive中的对象。 创建TaskFactory的新实例,而不是使用TaskFactory::StartNew。 我认为红色的波形是一个intellisense解析器错误,我在我的VS2017中也看到了它。 工作代码如下:

// "Expensive": Want to return an instance of this from a long running task..
public ref class Expensive
{
public:
    static Expensive^ CreateExpensively(Object^ argObj)
    {
        Arguments^ args = (Arguments^) argObj;  // you can pass it Arguments here
        // Do slow stuff with arguments, then create. 
        // <Imagine slow synchronous code here....>

        return gcnew Expensive();
    }

    Task<Expensive^>^ ExpensivelyCreateAsync(String^ s, int n)
    {
        auto func = gcnew Func<Object^, Expensive^>(&Expensive::CreateExpensively);
        Arguments^ args = gcnew Arguments(s, n);

        // Use Task instead of StartNew
        Task<Expensive^>^ asyncTask = gcnew Task<Expensive^>(func, args);
        asyncTask->Start();
        return asyncTask;
    }
};
它必须是'Func'。intellisense解析器错误是,嗯,呃。任务在C++/CLI中没有什么乐趣,您找到了一个很好的理由将此代码移到C库中。它必须是“Func”。intellisense解析器错误是,嗯,呃。任务在C++/CLI中没有什么乐趣,您找到了一个很好的理由将此代码移到C库中。