已解决:我错误地认为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();
}
}
}
答案 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。