我发现我可以使用Visual 2015中的关键字__resumable
和__await
来做一些与C#的async
/ C++中的await
非常相似的事情。
现在我想知道是否有一种在C++/Cli中使用__await
来执行TPL任务的方法?
发布于 2019-07-28 06:38:28
有三个主要障碍:
<mutex>
、<condition_variable>
和<future>
(尽管<mutex>
似乎适合于VisualStudio2019)。通过使用原始的WinAPI结构实现自己的库,我克服了这个限制。但我想这有点极端。或者,您可以转发声明所有禁止的类型(但您必须在任何地方使用另一个级别的间接方向)await
/ co_await
,必须使用/await标志编译C++模块,这是不允许使用/clr标志的。co_await
的函数的返回类型必须实现特定的概念(基本上,编译器在使用co_await
时内部调用的一组函数)。您不能像在C#中那样使用空返回值,其他托管返回值也没有意义。我发现唯一起作用的东西(一旦我克服了限制1)是将本机awaitable类型(您自己实现的未来/任务)转换为托管Task^
,可以在C#代码中等待。
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类型是一个简单的类型,它有一个执行实际转换的方法。以下是一个例子:
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())));
}
}
};
https://stackoverflow.com/questions/38075786
复制相似问题