从本机(C ++)线程通过Marshal.GetFunctionPointerForDelegate调用托管函数(C#)

时间:2015-08-18 01:21:29

标签: c# c++ .net multithreading interop

我正在使用Marshal.GetFunctionPointerForDelegate来获取指向本机函数的函数指针。然后我通过常规的DllImport机制将此函数指针传递给一些非托管代码。我用它来回调;本机代码调用回托管(C#)代码。只要回调发生在同一个线程上,一切正常。如果我尝试从我通过CreateThread创建的线程调用托管函数,则会失败。

是否可以通过GetFunctionPointerForDelegate返回的函数指针从本机线程回调托管代码?

C#:

//in class definition
[DllImport("SomeDll")]
public static extern void SetCallback(System.IntPtr function);

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public void delegate SomeDelgateType();

public SomeDelgateType OnCallback;

//a function to implement the callback
public void Callback()
{
}

//inside a setup function
OnCallback = new SomeDelgateType(Callback);
SetCallback(Marshal.GetFunctionPointerForDelegate(OnCallback);

当我从C ++调用函数指针时会出现问题。如果它在创建SetCallback函数的原始线程上一切正常。如果我使用CreateThread创建一个本机线程,然后尝试通过指针调用该函数,我会得到以下异常:

    Unhandled exception at 0x76674598 (KernelBase.dll) in      MissionControl.exe: 0xE0434352 (parameters: 0x80070057, 0x00000000, 0x00000000, 0x00000000, 0x73DB0000).

使用以下堆栈跟踪:

        KernelBase.dll!_RaiseException@16()    Unknown
        clr.dll!RaiseTheExceptionInternalOnly(class Object *,int,int)   Unknown
        clr.dll!IL_Throw(class Object *)    Unknown
        02bbc34b()  Unknown
        [Frames below may be incorrect and/or missing]  
        [External Code] 
        native_function_on_different_thread();

1 个答案:

答案 0 :(得分:2)

事实证明,您实际上可以从非托管线程调用。问题在于,如果您正在调试托管应用程序,回调中的断点实际上不会出现在调试器中,但您的代码仍将被执行。要使断点正常工作,您需要启用“本机代码调试”(即使断点位于托管代码中!),方法是转到项目 - > 属性 - > 调试 - > 启用本机代码调试