5

気が狂いそうな質問があります。私はこのバグを追跡するのに 1 週​​間を費やしました。ここにあります:

 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 *エラーが発生します。古い W​​inproc ポインターに存在するアンマネージ コードが GC されるのはなぜですか? これを追加すると:

oldProcHolder = (User.WindowProc)Marshal.GetDelegateForFunctionPointer(old_window_proc, typeof(User.WindowProc));

SetWindowLong() の直後に保持され、エラーは発生しません。

私がまったく理解していないのは、古いアンマネージ コードがガベージ コレクションの対象になる理由だと思いますか? それは私を夢中にさせています。前もって感謝します!

4

1 に答える 1

0

GetDelegateForFunctionPointer 関数を使用すると、アンマネージ関数がマネージ コード、つまりデリゲートに変換されます。デリゲートはマネージ コードであるため、ガベージ コレクション プロセスは自動的に実行されます。したがって、GetDelegateForFunctionPointer 関数は自動ガベージ コレクションの対象となります。

于 2012-10-24T13:51:32.193 に答える