我有一个问题让我发疯。我花了一周的时间追查这个错误,可能只是我对互操作的理解不如我想的那么好。这里是:
public class User
{
public const int GWL_WNDPROC = -4;
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, User.WindowProc newProc);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
public delegate IntPtr WindowProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
}
那是我的基本 User32 包装器。现在这样称呼:
class MyClass
{
private User.WindowProc proc;
public void MyMethod()
{
proc = new User.WindowProc(WndProc);
old_window_proc = User.SetWindowLong(handle,User.GWL_WNDPROC,proc);
}
}
强制垃圾回收:
GC.Collect();
GC.WaitForPendingFinalizers();
然后调用这个:
User.CallWindowProc(old_window_proc,hWnd, (uint)message.Msg,message.WParam,message.LParam);
我收到 * CallbackOnCollectedDelegate *错误。为什么旧 Winproc 指针处存在的非托管代码会被 GC 处理?如果我添加这个:
oldProcHolder = (User.WindowProc)Marshal.GetDelegateForFunctionPointer(old_window_proc, typeof(User.WindowProc));
在 SetWindowLong() 之后,它会一直保持它并且没有错误。
我想我根本不明白为什么旧的非托管代码有资格进行垃圾收集?它快把我逼疯了。提前致谢!