Ошибка компиляции при создании System :: Threading :: Tasks в C ++ / CLI. Невозможно определить ошибку - PullRequest
0 голосов
/ 06 января 2019

Я пытаюсь сделать слой-обертку C ++ / CLI (который вызывает в неуправляемую DLL-библиотеку C ++) доступными для моего уровня C # функциями, которые возвращают Task<T>. Неуправляемые функции дороги, поэтому я хотел асинхронные версии.

Но я не могу заставить его строить.

Мой подход заключается в использовании TaskFactory :: StartNew в C ++ / CLI, предоставляющем System :: Func который принимает один аргумент и возвращает одно значение. Прототип этого в MSDN выглядит следующим образом:

StartNew<TResult>(Func<Object,TResult>, Object)

(Кажется, я должен использовать это, если я хочу, чтобы моя созданная задача передавала аргументы в мою дорогую, синхронную функцию. Я делаю "Объект", содержащий все необходимые мне аргументы, упакованный во некоторый внутренний класс . Мой код может распаковать его и использовать их.)

Ниже приведен простой пример C ++ / CLI, который я попытался показать, чтобы показать проблему. И ниже это ошибки, которые я получаю. Я четко идентифицировал проваливающуюся строку с «ЭТА ЛИНИЯ ОТКАЗА». Есть также другая строка, которая показана с красным Squiggly в Visual Studio, но не вызывает ошибку компилятора.

Код (Это все в 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);

и сообщение, которое оно выдает мне, когда я нахожу на него указатель, "ожидается спецификатор типа". Но это не приводит к ошибке компиляции.

Кто-нибудь может увидеть, что я здесь делаю неправильно?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...