C# 在lambda中放置操作会导致C中的SystemAccessViolation#

C# 在lambda中放置操作会导致C中的SystemAccessViolation#,c#,opentk,C#,Opentk,我不明白为什么在我取消对调用操作的行的注释时,下面的代码会发生systemaccessinvalition GL.Enable(EnableCap.DebugOutput); GL.Enable(EnableCap.DebugOutputSynchronous); Action action = () => { Console.WriteLine("Hello"); }; DebugProc debugProc = (source, type, id, severity, length

我不明白为什么在我取消对调用操作的行的注释时,下面的代码会发生
systemaccessinvalition

GL.Enable(EnableCap.DebugOutput);
GL.Enable(EnableCap.DebugOutputSynchronous);

Action action = () => { Console.WriteLine("Hello"); };

DebugProc debugProc = (source, type, id, severity, length, message, userParam) =>
{
    string msg = Marshal.PtrToStringAnsi(message, length);
    Console.WriteLine("Debug message: " + msg);
    // Uncommenting this causes a SystemAccessViolation.
    //action.Invoke();
};

GL.DebugMessageCallback(debugProc, IntPtr.Zero);
当我在非调试模式下运行它时,我得到:

Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
    at OpenTK.Graphics.OpenGL4.GL.BufferData[T2](BufferTarget target, Int32 size, T2[] data, BufferUsageHint usage)
当我通过调试运行它时,我得到:

Unexpected exception: Object reference not set to an instance of an object.
Stack trace:
    at System.StubHelpers.StubHelpers.CheckCollectedDelegateMDA(IntPtr pEntryThunk)
    at OpenTK.Graphics.OpenGL4.GL.BufferData[T2](BufferTarget target, Int32 size, T2[] data, BufferUsageHint usage)

我也不确定我的问题是否应该向OpenTK报告,或者我是否在C#(使用C#8、.NETFramework4.8)中出错

只要在lambda中调用操作并注释掉,上述代码就可以正常工作

对于任何不熟悉OpenGL的人来说,
GL.DebugMessageCallback()
很可能会做一些本机工作。正因为如此,我不知道这是否意味着C#失去了对动作的跟踪,并尝试做一些它不应该做的事情,或者OpenGL正在做的某些事情对我编写的代码不好。GC是否可能已经清理了
操作
,并试图调用它?不过,在这一点上,我是在猜测

action()
未注释时,我无法在其内部放置断点,断点不会被触发。但是,当
action()
被完全注释掉时,我可以使断点工作。调用的顺序与它是在lambda的顶部还是底部无关。

“是否有可能GC已经清理了该操作并试图调用它?”--是的,当然有可能。在调试器下运行时,堆栈跟踪中存在
CheckCollectedDelegateMDA()
,这实际上可以确定发生了什么。请参阅标记的副本。有关建议,请参见。在您的示例中,添加
GC.KeepAlive(操作)在调用
GL.DebugMessageCallback
后应该修复它,假设这是您使用
debugProc
的唯一地方。您是否遇到了可能的问题?“GC是否已经清理了该操作并试图调用它?”--是的,当然可能。在调试器下运行时,堆栈跟踪中存在
CheckCollectedDelegateMDA()
,这实际上可以确定发生了什么。请参阅标记的副本。有关建议,请参见。在您的示例中,添加
GC.KeepAlive(操作)GL.DebugMessageCallback
调用之后,code>应该会修复它,假设这是您唯一使用
debugProc
的地方。您可能遇到了什么问题?