我正在包装一个用于.NET使用的C 库。C API中有返回std::future
的功能。我想让.NET代理类返回System.Threading.Tasks.Task
。
我想到在C 方面添加一种替换方法,该方法除了使用方法参数外还将采用功能指针。然后,我可以启动一个新线程(例如使用std::async
(,并在std::future::get
上等待。std::future::get
返回后,我可以将传递的功能指针拨打。在c#侧,我将将A指针传递给可以完成返回任务的函数。类似:
Task CallCpp(int a, int b) {
TaskCompletionSource<int> tcs;
Action callback = () => tcs.SetResult(0);
IntPtr callbackPtr = Marshal.GetFunctionPointerForDelegate(callback);
CppMethod(callbackPtr, a, b);
return tcs.Task;
}
[DllExport]
external void CppMethod(IntPtr callback, int a, int b);
void CppMethod(void (*callback)(), int a, int b) {
std::future f = realmethod(a, b);
std::async([&]{ f.get; callback(); });
}
std::future realmethod(int a, int b);
(是的,代码有内存管理问题。虽然足以使这个想法跨越(
编组异步完成或失败是相对容易的部分。我将亲自使用C#中实现的COM接口,标记为[InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]
,并使用setCompleted()
和setFailed( HRESULT status )
等2种方法,然后在我启动任务时通过它,但这是一个口味问题。
问题是缺少C 多线程实现。
bubost在这方面更好,它的future
类具有then
方法,可用于传播状态而无需阻止线程。
目前,标准C 期货没有提供任何可比的东西。我认为你不幸。
如果您可以修改C 库,请将API更改为更有意义的事物,即可以以非阻滞方式通知完成。
没有com,终生管理很复杂。在启动异步任务但完成之前,C#Side上的某人需要保留该功能指针。这是一个可能的解决方案,请注意它如何使用gchandle使回调要结束任务:
[UnmanagedFunctionPointer( CallingConvention.Cdecl )]
delegate void pfnTaskCallback( int hResult );
[DllImport( "my.dll" )]
static extern void launch( [MarshalAs( UnmanagedType.FunctionPtr )] pfnTaskCallback completed );
public static async Task runAsync()
{
var tcs = new TaskCompletionSource<bool>();
pfnTaskCallback pfn = delegate ( int hr )
{
if( hr >= 0 ) // SUCEEDED
tcs.SetResult( true );
else
tcs.SetException( Marshal.GetExceptionForHR( hr ) );
};
var gch = GCHandle.Alloc( pfn, GCHandleType.Normal );
try
{
launch( pfn );
await tcs.Task;
}
finally
{
gch.Free();
}
}