尝试加载150+灰度4096 x 4096位图。我认为需要帮助来解决2GB的限制

时间:2013-03-18 02:19:12

标签: c# winforms

已解决:我错误地认为Visual Studio 2012默认在制作新项目时构建64位应用程序。在解决方案属性,构建选项卡下,有一个标记为“首选32位”的复选框。当我取消选中此复选框并重建我的解决方案时,我能够一次加载和处理超过200个位图。感谢Mike Trusov如此礼貌地向我指出解决方案。

原始问题:我遇到了一个小问题。我有超过150个灰度位图,我想在8 GB系统上加载到RAM中,但我似乎无法超过50左右而不会抛出异常。我已经尝试将位图加载到一个数组中,这当然是一个失败的原因,因为.NET有2GB的限制。但它早在2GB的位图加载之前就失败了。所以我尝试将它们加载到List<List<Bitmap>>中,但即便在同一个地方也失败了。在异常时刻,任务管理器说我有3939 MB的可用RAM等待填充。很奇怪。

我不需要这些位图在RAM中连续。对于我所关心的所有内容,它们可能是分散的16 MB分配。我只想用一堆位图来填充可用的RAM。就是这样。

异常在不同时间是OutOfMemory异常或ArgumentException,具体取决于我启动程序时可用的RAM量。在任何一种情况下,堆栈跟踪都在System.Drawing.Bitmap..ctor(String filename)内部死亡。在异常时加载的特定文件没有任何问题。事实上,当我加载一组不同(甚至重叠)的位图时,错误会在同一次迭代中发生。

有没有人知道他们可以借给我如何做到这一点?我是否以某种奇怪的方式进入.NET 2GB限制?

回答几个问题和评论:我在拥有8 GB RAM的计算机上使用Visual Studio 2012,.NET 4.5,64位Windows 7。是的,出于各种原因(性能,图像处理等原因),我需要同时在RAM中使用所有这些位图。我已经考虑使用gcAllowVeryLargeObjects,但我不需要或想要所有的位图在一大块连续的内存中。我宁愿每个Bitmap都使用自己独立的内存分配。此外,如果我有一台64 GB RAM的机器,那么限制在那个大小的150位图是荒谬的。为什么这些位图不会在不抛出OutOfMemoryException的情况下加载?

对我而言,.NET似乎试图将所有位图保留在一个2 GB的区域内。如果有一种方法可以让每个Bitmap(比我在这里说的更多)拥有自己独立的地址空间,那么可能会解决问题。为了调用很久以前MS-DOS的语言,我想使用长指针分配和访问远存储器,而不是让我的所有数据都停留在一个近段。

这是数组代码:

    List<String> imageFiles;            // List of .bmp filenames.
    Bitmap[] bmps = new Bitmap[100];    // Stores/accesses the Bitmaps.

    private void goButton_Click(object sender, EventArgs e)
    {
        int i;

        // Load the bitmaps
        if (bmps[0] == null)
        {
            // Load the list of bitmap files.
            imageFiles = Directory.EnumerateFiles(@"C:\Temp", "*.bmp", SearchOption.TopDirectoryOnly).ToList();

            // Read bitmap files
            for (i = 0; i < bmps.Length; ++i)
            {
                bmps[i] = new Bitmap(imageFiles[i]);    // <-- Exception occurs here when i == 52 or so.
            }
        }
    }

这是List&gt;代码:

    List<String> imageFiles;                                // List of .bmp filenames.
    List<List<Bitmap>> bmps = new List<List<Bitmap>>(100);  // Stores/accesses the Bitmaps.

    private void goButton_Click(object sender, EventArgs e)
    {
        int i;

        // Load the bitmaps
        if (bmps.Count == 0)
        {
            // Load the list of bitmap files.
            imageFiles = Directory.EnumerateFiles(@"C:\Temp", "*.bmp", SearchOption.TopDirectoryOnly).ToList();

            // Read bitmap files
            for (i = 0; i < 100; ++i)
            {
                // Load the bitmap into temporary Bitmap b.
                Bitmap b = new Bitmap(imageFiles[i]);   // <-- Exception occurs here when i == 52 or so.

                // Create and add a List<Bitmap> that will receive the clone of Bitmap b.
                bmps.Add(new List<Bitmap>(1));

                // Clone Bitmap b and add that cloned Bitmap to the Bitmap of List<Bitmap>.
                bmps[i].Add((Bitmap)b.Clone());

                // Dispose Bitmap b.
                b.Dispose();
            }
        }
    }

2 个答案:

答案 0 :(得分:1)

在64位应用程序中加载超过2GB的位图到内存中应该没有问题(检查项目设置 - 可能需要为基于x86的任何CPU创建新配置)在64位操作系统上运行(我猜测你是)。另外一个简单的列表应该有效:

    var imageFiles = Directory.EnumerateFiles(@"C:\Temp", "*.bmp", SearchOption.TopDirectoryOnly).ToList();
    var lst = new List<Bitmap>();
    foreach (var imageFile in imageFiles)
    {
        lst.Add(new Bitmap(imageFile));
    }

答案 1 :(得分:0)

他们 所有 是否必须同时加载?你可以加载说,其中20个,然后当你正在处理或显示那些时,你有一个后台线程准备下一个20。