C# 为什么GC使下面的代码段失败

C# 为什么GC使下面的代码段失败,c#,.net,image,bitmap,unmanaged,C#,.net,Image,Bitmap,Unmanaged,我对.NET如何管理图像有点困惑,我有以下代码,从非托管HBitmap构建一个托管位图,保留alpha通道 public static Bitmap GetBitmapFromHBitmap(IntPtr nativeHBitmap) { Bitmap bmp = Bitmap.FromHbitmap(nativeHBitmap); if (Bitmap.GetPixelFormatSize(bmp.PixelFormat) < 32)

我对.NET如何管理图像有点困惑,我有以下代码,从非托管HBitmap构建一个托管位图,保留alpha通道

    public static Bitmap GetBitmapFromHBitmap(IntPtr nativeHBitmap)
    {
        Bitmap bmp = Bitmap.FromHbitmap(nativeHBitmap);

        if (Bitmap.GetPixelFormatSize(bmp.PixelFormat) < 32)
            return bmp;

        BitmapData bmpData;

        if (IsAlphaBitmap(bmp, out bmpData))
        {
            // MY QUESTION IS RELATED TO THIS
            // IF CALL SUPPRESS_FINALIZE THE OBJECT
            // IT WILL WORK, OTHERWISE IT FAILS
            GC.SuppressFinalize(bmp);

            return new Bitmap(
                bmpData.Width,
                bmpData.Height,
                bmpData.Stride,
                PixelFormat.Format32bppArgb,
                bmpData.Scan0);
        }

        return bmp;
    }

    private static bool IsAlphaBitmap(Bitmap bmp, out BitmapData bmpData)
    {
        Rectangle bmpBounds = new Rectangle(0, 0, bmp.Width, bmp.Height);

        bmpData = bmp.LockBits(bmpBounds, ImageLockMode.ReadOnly, bmp.PixelFormat);

        try
        {
            return IsAlphaBitmap(bmpData);
        }
        finally
        {
            bmp.UnlockBits(bmpData);
        }
    }

    private static bool IsAlphaBitmap(BitmapData bmpData)
    {
        for (int y = 0; y <= bmpData.Height - 1; y++)
        {
            for (int x = 0; x <= bmpData.Width - 1; x++)
            {
                Color pixelColor = Color.FromArgb(
                    Marshal.ReadInt32(bmpData.Scan0, (bmpData.Stride * y) + (4 * x)));

                if (pixelColor.A > 0 & pixelColor.A < 255)
                {
                    return true;
                }
            }
        }

        return false;
    }
公共静态位图GetBitmapFromHBitmap(IntPtr nativeHBitmap)
{
位图bmp=位图.FromHbitmap(nativeHBitmap);
if(位图.GetPixelFormatSize(bmp.PixelFormat)<32)
返回bmp;
位图数据bmpData;
if(isalHabitMap(bmp,out bmpData))
{
//我的问题与此有关
//如果调用SUPPRESS\u,则完成对象
//它会工作的,否则它会失败
气相色谱法(bmp);
返回新位图(
bmpData.Width,
bmpData.高度,
bmpData.Stride,
PixelFormat.Format32bppArgb,
bmpData.Scan0);
}
返回bmp;
}
专用静态布尔ISALPABITMAP(位图bmp,输出位图数据bmpData)
{
矩形bmpBounds=新矩形(0,0,bmp.Width,bmp.Height);
bmpData=bmp.LockBits(bmpBounds,ImageLockMode.ReadOnly,bmp.PixelFormat);
尝试
{
返回isalHabitMap(bmpData);
}
最后
{
bmp.UnlockBits(bmpData);
}
}
专用静态bool IsAlphaBitmap(位图数据bmpData)
{

对于(int y=0;y请查看

调用者负责分配和释放scan0参数指定的内存块。但是,在释放相关位图之前,不应释放内存。

这意味着您需要确保保留
bmpData
指向的底层内存块,直到释放
GetBitmapFromHBitmap
返回的
Bitmap
实例

导致您的问题的原因是垃圾收集器检测到
bmp
无法访问(未使用)因此收集/终结它,这肯定会释放底层内存块,但是即使你抑制终结器,你仍然调用了
UnlockBits
,这意味着
bmpData
无论如何都是无效的-此时它可能会工作,但这完全是偶然的上述代码正确您需要找到一种机制,使
bmpData
(并扩展为
bmp
)在返回的
Bitmap
实例存在的时间内保持有效,即可能对您的应用程序进行重大更改


或者,请查看一种完全不同的方法来实现(我认为)您想要实现的目标,同时完全避免所有这些问题。

请看一看

调用者负责分配和释放scan0参数指定的内存块。但是,在释放相关位图之前,不应释放内存。

这意味着您需要确保保留
bmpData
指向的底层内存块,直到释放
GetBitmapFromHBitmap
返回的
Bitmap
实例

导致您的问题的原因是垃圾收集器检测到
bmp
无法访问(未使用)因此收集/终结它,这肯定会释放底层内存块,但是即使你抑制终结器,你仍然调用了
UnlockBits
,这意味着
bmpData
无论如何都是无效的-此时它可能会工作,但这完全是偶然的上述代码正确您需要找到一种机制,使
bmpData
(并扩展为
bmp
)在返回的
Bitmap
实例存在的时间内保持有效,即可能对您的应用程序进行重大更改

或者,你可以用一种完全不同的方式去做(我认为)你想要实现的事情,同时完全避免所有这些问题