我有一个让我疯狂的问题.我花了一个星期追逐这个bug,可能只是我不理解互操作以及我认为.这里是:
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);
}
Run Code Online (Sandbox Code Playgroud)
这是我的基本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);
}
}
Run Code Online (Sandbox Code Playgroud)
强制垃圾收集:
GC.Collect();
GC.WaitForPendingFinalizers();
Run Code Online (Sandbox Code Playgroud)
然后打电话给:
User.CallWindowProc(old_window_proc,hWnd, (uint)message.Msg,message.WParam,message.LParam);
Run Code Online (Sandbox Code Playgroud)
我得到一个*CallbackOnCollectedDelegate*错误.为什么旧的Winproc指针中存在的非托管代码会得到GC?如果我添加这个:
oldProcHolder = (User.WindowProc)Marshal.GetDelegateForFunctionPointer(old_window_proc, typeof(User.WindowProc));
Run Code Online (Sandbox Code Playgroud)
在SetWindowLong()之后,它保持它并且没有错误.
我想我不理解的是为什么旧的非托管代码有资格进行垃圾收集?这让我疯了.提前致谢!
GetDelegateForFunctionPointer 函数在使用时将非托管函数转换为托管代码,即委托。由于任何委托都是托管代码,因此垃圾收集过程会自动运行。因此 GetDelegateForFunctionPointer 函数符合自动垃圾回收的条件。