2

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

原始问题:我遇到了一个小问题。我有超过 150 个灰度位图,我想在 8 GB 系统上加载到 RAM 中,但如果不抛出异常,我似乎无法超过 50 个左右。我已经尝试将位图加载到一个数组中,这当然是一个失败的原因,因为 .NET 有 2GB 的限制。但它在加载 2GB 的位图之前很久就失败了。所以我尝试将它们加载到 aList<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,但我不需要或不希望我的所有位图都放在一大块连续的内存中。我宁愿每个位图都使用自己单独的内存分配。此外,如果我有一台具有 64 GB RAM 的机器,那么即使限制为 150 个这种大小的位图也是荒谬的。为什么不抛出 OutOfMemoryException 就无法加载这些位图?

对我来说,.NET 似乎试图将所有位图保存在一个 2 GB 的区域中。如果有办法让每个位图(这里说的比我知道的更多)都有自己独立的地址空间,那可能会解决问题。为了调用很久以前的 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<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();
            }
        }
    }
4

2 回答 2

1

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

    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));
    }
于 2013-03-18T02:37:16.990 回答
0

它们必须同时加载吗?您能否加载其中的 20 个,然后在您处理或显示这些时,您有一个后台线程准备接下来的 20 个。

于 2013-03-18T02:35:44.150 回答