检测到CallbackOnCollectedDelegate

我是一个应用程序的子类。 我的子类Window过程在DLL中。 我在DLL中的子类代码看起来有点像这样(剥离,删除其他非相关部分)。

class FooBar { private delegate int WndProcDelegateType(IntPtr hWnd, int uMsg, int wParam, int lParam); private const int GWL_WNDPROC = (-4); private static IntPtr oldWndProc = IntPtr.Zero; private static WndProcDelegateType newWndProc = new WndProcDelegateType(MyWndProc); internal static bool bHooked = false; [DllImport("user32.dll")] private static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, WndProcDelegateType dwNewLong); [DllImport("user32.dll")] private static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong); [DllImport("user32")] private static extern int CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, int Msg, int wParam, int lParam); private static int MyWndProc(IntPtr lhWnd, int Msg, int wParam, int lParam) { switch (Msg) { // the usual stuff // finally return CallWindowProc(oldWndProc, lhWnd, Msg, wParam, lParam); } internal static void Hook() { oldWndProc = SetWindowLong(hWnd, GWL_WNDPROC, newWndProc); bHooked = oldWndProc != IntPtr.Zero; } internal static void Unhook() { if (bHooked) SetWindowLong(hWnd, GWL_WNDPROC, oldWndProc); } } 

现在,即使我在委托的类级静态实例变量中持有对WndProc的强引用,我也会收到此错误。

检测到CallbackOnCollectedDelegate

消息:对类型为“PowerPointAddIn1!FooBar + WndProcDelegateType :: Invoke”的垃圾回收委托进行了回调。 这可能会导致应用程序崩溃,损坏和数据丢失。 将委托传递给非托管代码时,托管应用程序必须保持它们的活动状态,直到确保它们永远不会被调用。

我究竟做错了什么?

 oldWndProc = SetWindowLong(hWnd, GWL_WNDPROC, MyWndProc); 

这迫使C#动态创建委托对象。 它将代码转换为:

 oldWndProc = SetWindowLong(hWnd, GWL_WNDPROC, new WndProcDelegateType(MyWndProc)); 

这是一个问题,委托对象没有被引用到任何地方。 下一个垃圾收集将破坏它,从非托管代码下拉出地毯。 你已经在你的代码中做了正确的事情,你只是忘了使用它。 固定:

 oldWndProc = SetWindowLong(hWnd, GWL_WNDPROC, newWndProc); 

从NativeWindow派生自己的类并使用其AssignHandle()方法是更好的捕鼠器顺便说一句。 当您看到WM_DESTROY消息时调用ReleaseHandle()。

叫我疯了,但存储引用应该解决这个问题:

  private static readonly WndProcDelegateType _reference = MyWndProc; 

可以在调用返回后调用回调函数,受管理的调用者必须采取措施以确保在回调函数完成之前代理保持未收集状态。 有关防止垃圾回收的详细信息,请参阅使用平台调用进行Interop Marshaling。

http://msdn.microsoft.com/en-us/library/eaw10et3.aspx