Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用.Clone()剪切位图时内存不足_C#_Asp.net_.net - Fatal编程技术网

C# 使用.Clone()剪切位图时内存不足

C# 使用.Clone()剪切位图时内存不足,c#,asp.net,.net,C#,Asp.net,.net,我试图从用户上传的图像中自动生成缩略图,但我总是遇到“内存不足”的异常情况。 据我所知,当您指定图像外部的起始位置或宽度/高度时,即使我这样做,也会引发内存不足异常 var rct = new Rectangle(5, 5, 10, 10); var whatever = bitmap.Clone(rct, bitmap.PixelFormat); 在800x900像素的图像上,我仍然会遇到“内存不足”的异常,我无法找出它的问题所在,也无法从其他线程中得到任何好的答案,因为所有关于OOM异常的

我试图从用户上传的图像中自动生成缩略图,但我总是遇到“内存不足”的异常情况。 据我所知,当您指定图像外部的起始位置或宽度/高度时,即使我这样做,也会引发内存不足异常

var rct = new Rectangle(5, 5, 10, 10);
var whatever = bitmap.Clone(rct, bitmap.PixelFormat);
在800x900像素的图像上,我仍然会遇到“内存不足”的异常,我无法找出它的问题所在,也无法从其他线程中得到任何好的答案,因为所有关于OOM异常的事情都是超出图像边界的错误。 有人对此有解释或解决办法吗

编辑:更多的上下文

图像的循环

foreach (var blob in fileInfoList)
{
    var blockBlobName = CheckExistence(BaseBlobUrl, blob.FileName, blob.FileNameWithoutExtension);

    var image = new Image()
    {
        BlobUrl = Path.Combine(BaseBlobUrl, blockBlobName),
        FullName = blob.FileName,
        FileName = blob.FileNameWithoutExtension,
        BlockBlobName = blockBlobName,
        OwningOrganizationId = CurrentUser.UserOrganization.OrganizationId,
        ThumbnailUrl = CreateThumbnail(blob.File, blockBlobName),
        Name = "Whatever"
    };

    blobList.Add(image);

    RepositoryFactory.AzureStorageRepository.SaveImage(blob.File, blockBlobName, blob.ContentType, CurrentUser.UserOrganization.Organization.Id);
}
由列表中的每个图像调用以生成缩略图的方法

public string CreateThumbnail(byte[] b, string parentImageName)
    {
        Bitmap bmp;

        using (var ms = new MemoryStream(b))
        {
            bmp = new Bitmap(ms);
        }

        Bitmap thumbnail = bmp;

        Rectangle rect = new Rectangle(5, 5, 10, 10);

        if (bmp.Width > bmp.Height)
            thumbnail = bmp.Clone(rect, bmp.PixelFormat);
        else if (bmp.Height > bmp.Width)
            thumbnail = bmp.Clone(new Rectangle((bmp.Height/2) - (bmp.Width/2), 0, bmp.Width, bmp.Width), bmp.PixelFormat);

        byte[] bmpArray = new byte[0];

        using (var ms = new MemoryStream())
        {
            finalCrop.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
            ms.Close();

            bmpArray = ms.ToArray();
        }

        var name = "Thumbnail_" + parentImageName;

        RepositoryFactory.AzureStorageRepository.SaveThumbnail(bmpArray, name, "jpg/image", CurrentUser.UserOrganization.Organization.Id);

        return BaseBlobUrl + "thumbnails/" + name;


    }

我认为你遇到的问题是位图需要处理。如果一个人在没有释放其底层非托管内容(即被处置)的情况下被垃圾收集,那么该内存将无法恢复

还请注意,您需要处理这两个位图。最好的做法是将它们包装在一个容器中,如下所示:

        using (var ms = new MemoryStream(b))
        {
            using (Bitmap bmp = new Bitmap(ms))
            using (Bitmap thumbnail = bmp)
            {

                Rectangle rect = new Rectangle(5, 5, 10, 10);

                if (bmp.Width > bmp.Height)
                    thumbnail = bmp.Clone(rect, bmp.PixelFormat);
                else if (bmp.Height > bmp.Width)
                    thumbnail = bmp.Clone(new Rectangle((bmp.Height / 2) - (bmp.Width / 2), 0, bmp.Width, bmp.Width), bmp.PixelFormat);

                byte[] bmpArray = new byte[0];

                using (var ms = new MemoryStream())
                {
                    finalCrop.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
                    ms.Close();

                    bmpArray = ms.ToArray();
                }

                var name = "Thumbnail_" + parentImageName;

                RepositoryFactory.AzureStorageRepository.SaveThumbnail(bmpArray, name, "jpg/image", CurrentUser.UserOrganization.Organization.Id);

                return BaseBlobUrl + "thumbnails/" + name;
            }
        }

值得注意的是,
使用
将调用其目标上的
Dispose()
,即使抛出异常(因此具有与@Scott Chamberlain answer相同的
最终
类型功能

好的,因此我通过处理位图找到了问题的答案。 在这段代码之后

Bitmap thumbnail = bmp;
我补充说

bmp.Dispose();
在调试过程中,我注意到bmp中的所有属性都没有保留在名为缩略图的位图中,因此我将其更改为以下内容

Bitmap thumbnail = new Bitmap(bmp);

感谢大家告诉我如何处置位图!

以下是正确处置对象的方法

Bitmap bmp = null;
Bitmap thumbnail = null;

try
{
    using (var ms = new MemoryStream(b))
    {
        bmp = new Bitmap(ms);
    }

    Rectangle rect = new Rectangle(5, 5, 10, 10);

    if (bmp.Width > bmp.Height)
        thumbnail = bmp.Clone(rect, bmp.PixelFormat);
    else if (bmp.Height > bmp.Width)
        thumbnail = bmp.Clone(new Rectangle((bmp.Height/2) - (bmp.Width/2), 0, bmp.Width, bmp.Width), bmp.PixelFormat);
    else
        thumbnail = bmp;



    byte[] bmpArray = new byte[0];

    using (var ms = new MemoryStream())
    {
        finalCrop.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
        ms.Close();

        bmpArray = ms.ToArray();
    }

    var name = "Thumbnail_" + parentImageName;

    RepositoryFactory.AzureStorageRepository.SaveThumbnail(bmpArray, name, "jpg/image", CurrentUser.UserOrganization.Organization.Id);

    return BaseBlobUrl + "thumbnails/" + name;
}
finally
{
    if(bmp != null)
        bmp.Dispose();

    if(thumbnail != null)
        thumbnail.Dispose(); //If bmp and thumbnail are the same object this is still safe to do.
}

使用try/finally块确保即使在发生错误的情况下也能处理对象。执行额外的
位图缩略图=新位图(bmp)
在您的答案中,只会生成一个您忘记处理的额外位图。

您是在循环中执行此操作的,不是吗?生成缩略图的方法是从循环中调用的,因为用户可以同时上载多个图像。您是否可以提供更多的代码,包括循环上下文请注意,您从来都不是
Dis姿势
ing图像/位图;这是一个非常糟糕的主意,因为有大量与对象相关的本机资源,其中一些资源非常有限(例如GDI+句柄).GDI+并非真正设计用于服务器,因此请小心。您尝试过的所有图像都会出现问题吗?我无法再现您看到的问题,请注意,GDI+中的OOM可能意味着许多不同的错误,而不仅仅是OOM或边界错误。您到底从何处获得异常?您似乎没有处理位图您可以在任何位置创建。除非您将位图返回到某个位置,否则您应该为位图添加一个
using
块。我可以使用
using
块,或者将
bmp.Dispose()放入
在try/finally块中。此外,您将dispose放在了错误的位置,它需要在两行
thumboil=bmp.Clone
之后进行处理。最后,您从未处理过
thumboil
。我发布了一个答案,显示了正确的处理方法。您当前的方法中有一些主要的错误,您无法立即看到,但可能会出错我们的程序在运行数小时后随机崩溃。是的,我将对方法中的所有位图使用>使用块。对于>克隆行,不再需要>bmp位图。