如何删除对象的旧副本C#

时间:2016-01-14 12:08:19

标签: c# image copy out-of-memory

我从一个公共变量中获取一个Image,在对该图像进行每次操作后,我都会在全局变量上创建一个副本,以便UI可以更新它。

但是有一段时间我有一个内存不足的异常,任何想法? 因为我没有复制尝试它,但后来我得到一个例外,因为我想重新加载图像,它已经在使用。

private void Start_Click(object sender, EventArgs e)
{
    Thread t = new Thread(transmit_pic);
    t.Start();
}
protected Bitmap CopyBitmap(Bitmap source)
{
    return new Bitmap(source);
}
private void transmit_pic()
{
    Bitmap b = new Bitmap(img);
    Bitmap bm = CopyBitmap(b);
    int size_X = bm.Width;
    int size_Y = bm.Height;

    int px = 255;
    Color Green  = Color.FromArgb(0,255,0);
    for (int h = 0; h < size_Y; h++)
    {
        for (int w = 0; w < size_X; w++)
        {
            px = (int)bm.GetPixel(w, h).G;
            if (px < 128)
            {
               // i shorted it a litel bit
               if(somethig not imprtend here){
                bm.SetPixel(w, h, Green);
                img = (Image)CopyBitmap(bm);
               }
            }
        }
    }
    Console.Write("DONE");
}
private void RELOAD_PIC_on_UI_Click(object sender, EventArgs e)
{
    pictureBox1.Image = img;
}

4 个答案:

答案 0 :(得分:1)

其他答案都有适合您的解决方案,但只是为了增加一些清晰度:

在C#中管理对象意味着不可能逐字地“删除对象的旧副本” - 只要框架的垃圾收集器决定这样做,它们就会被清除,这不是一个确定性的过程,而是取决于你的内存量电脑已经可用。

也就是说,有些东西不是由框架管理的,比如打开文件流和图像或数据库连接。框架不会自动关闭这些资源,因此无法清除使用它们的内存对象。 IDisposable接口和Dispose方法的目的是关闭这些非托管资源,以便自动垃圾收集可以清除对象并释放内存。

答案 1 :(得分:0)

你应该调用Bitmap.Dispose Method并确保没有引用旧的未使用的图像。

  

在释放对图像的最后一个引用之前,请始终调用Dispose。否则,在垃圾收集器调用Image对象的Finalize方法之前,不会释放它正在使用的资源。

答案 2 :(得分:0)

你可以调用Bitmap.Dispose,一般来说处理你不再需要的对象是个好习惯。

答案 3 :(得分:0)

你也可以使用using指令,因为.Dispose()允许你使你的代码更具可读性,在许多情况下你可以直接使用在using指令中返回所以你的对象将处置甚至你必须返回与之相关的你的:IDisposable对象。

private void transmit_pic()
{
    using(Bitmap b = new Bitmap(img))
    using(Bitmap bm = CopyBitmap(b))
    {
        int size_X = bm.Width;
        int size_Y = bm.Height;

        int px = 255;
        Color Green  = Color.FromArgb(0,255,0);
        for (int h = 0; h < size_Y; h++)
        {
            for (int w = 0; w < size_X; w++)
            {
                px = (int)bm.GetPixel(w, h).G;
                if (px < 128)
                {
                   // i shorted it a litel bit
                   if(somethig not imprtend here){
                    bm.SetPixel(w, h, Green);
                    img = (Image)CopyBitmap(bm);
                   }
                }
            }
        }
    }
    Console.Write("DONE");
}

在您的示例中,我们处理了Bitmap对象的b和bm实例。