已解决:我错误地假设 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();
}
}
}