C# 即使对于非常小的任务,内存不足也会出现异常
我有一个TCP应用程序,可以从客户端请求服务器上的文件夹中的图像。如果我需要一个小文件夹,它可以正常工作。如果它是一个大文件夹,它将抛出内存不足异常。但在这之后,即使是一个有1个文件的文件夹也会抛出同样的内存不足异常 我想它可能是内存不足的线程,所以我尝试将它放在一个单独的线程和任务上,但都不起作用。以下是我正在使用的代码:C# 即使对于非常小的任务,内存不足也会出现异常,c#,out-of-memory,C#,Out Of Memory,我有一个TCP应用程序,可以从客户端请求服务器上的文件夹中的图像。如果我需要一个小文件夹,它可以正常工作。如果它是一个大文件夹,它将抛出内存不足异常。但在这之后,即使是一个有1个文件的文件夹也会抛出同样的内存不足异常 我想它可能是内存不足的线程,所以我尝试将它放在一个单独的线程和任务上,但都不起作用。以下是我正在使用的代码: public static void Images(string path) { new Task(() => {
public static void Images(string path)
{
new Task(() =>
{
try
{
string root = lookupDirectoryPath("Application data");
string backupPath = root + @"\Apple Computer\MobileSync\";
string imagePath = backupPath + path;
if (Directory.Exists(imagePath))
{
String[] allfiles = Directory.GetFiles(imagePath, "*.*", SearchOption.AllDirectories);
List<Image> allImages = new List<Image>();
foreach (string file in allfiles)
{
using (FileStream stream = new FileStream(file, FileMode.Open, FileAccess.Read))
{
if (IsImage(stream))
{
allImages.Add(Image.FromFile(file));
}
}
}
if (allImages.Count > 0)
{
byte[] data = imageListToByteArray(allImages);
serverSendByteArray(data, 12);
}
else
{
serverSendByteArray(Encoding.Default.GetBytes("backup contained no images"), 1);
}
}
else
{
serverSendByteArray(Encoding.Default.GetBytes("iphone backup folder does not exist"), 1);
}
}
catch (Exception ex)
{
if (ex.GetType().IsAssignableFrom(typeof(OutOfMemoryException)))
{
serverSendByteArray(Encoding.Default.GetBytes("Out of memory, could not send iphone images"), 1);
}
else
{
serverSendByteArray(Encoding.Default.GetBytes("Unknown error, could not send iphone images"), 1);
}
}
}).Start();
}
公共静态无效图像(字符串路径)
{
新任务(()=>
{
尝试
{
string root=lookupDirectoryPath(“应用程序数据”);
字符串backupPath=root+@“\Apple Computer\MobileSync\”;
字符串imagePath=反向路径+路径;
if(Directory.Exists(imagePath))
{
字符串[]allfiles=Directory.GetFiles(imagePath,“**”,SearchOption.AllDirectories);
列表所有图像=新列表();
foreach(所有文件中的字符串文件)
{
使用(FileStream stream=newfilestream(file,FileMode.Open,FileAccess.Read))
{
if(IsImage(流))
{
allImages.Add(Image.FromFile(file));
}
}
}
如果(allImages.Count>0)
{
字节[]数据=imageListToByteArray(所有图像);
serverSendByteArray(数据,12);
}
其他的
{
serverSendByteArray(Encoding.Default.GetBytes(“备份不包含图像”),1);
}
}
其他的
{
serverSendByteArray(Encoding.Default.GetBytes(“iphone备份文件夹不存在”),1);
}
}
捕获(例外情况除外)
{
if(例如GetType().IsAssignableFrom(typeof(OutOfMemoryException)))
{
serverSendByteArray(Encoding.Default.GetBytes(“内存不足,无法发送iphone图像”),1);
}
其他的
{
serverSendByteArray(Encoding.Default.GetBytes(“未知错误,无法发送iphone图像”),1);
}
}
}).Start();
}
在allImages.Add(Image.FromFile(file)),抛出异常
这是isImage()函数:
public static bool IsImage(Stream stream)
{
stream.Seek(0, SeekOrigin.Begin);
List<string> jpg = new List<string> { "FF", "D8" };
List<string> bmp = new List<string> { "42", "4D" };
List<string> gif = new List<string> { "47", "49", "46" };
List<string> png = new List<string> { "89", "50", "4E", "47", "0D", "0A", "1A", "0A" };
List<List<string>> imgTypes = new List<List<string>> { jpg, bmp, gif, png };
List<string> bytesIterated = new List<string>();
for (int i = 0; i < 8; i++)
{
string bit = stream.ReadByte().ToString("X2");
bytesIterated.Add(bit);
bool isImage = imgTypes.Any(img => !img.Except(bytesIterated).Any());
if (isImage)
{
return true;
}
}
return false;
}
公共静态bool IsImage(流)
{
stream.Seek(0,SeekOrigin.Begin);
List jpg=新列表{“FF”,“D8”};
列表bmp=新列表{“42”,“4D”};
List gif=新列表{“47”、“49”、“46”};
列表png=新列表{“89”、“50”、“4E”、“47”、“0D”、“0A”、“1A”、“0A”};
List imgTypes=新列表{jpg,bmp,gif,png};
List bytesIterated=新列表();
对于(int i=0;i<8;i++)
{
字符串位=stream.ReadByte().ToString(“X2”);
字节迭代。添加(位);
bool isImage=imgTypes.Any(img=>!img.Except(bytesiiterated.Any());
如果(isImage)
{
返回true;
}
}
返回false;
}
感谢您的帮助尝试更改此设置
using (FileStream stream = new FileStream(file, FileMode.Open, FileAccess.Read))
{
if (IsImage(stream))
{
allImages.Add(Image.FromFile(file));
}
}
...
if (allImages.Count > 0)
{
byte[] data = imageListToByteArray(allImages);
serverSendByteArray(data, 12);
}
为此:
using (FileStream stream = new FileStream(file, FileMode.Open, FileAccess.Read))
{
if (IsImage(stream))
{
allImages.Add(Image.FromFile(file));
}
stream.Close();
}
....
if (allImages.Count > 0)
{
byte[] data = imageListToByteArray(allImages);
foreach(Image img in allImages)
{
img.Dispose();
}
serverSendByteArray(data, 12);
}
Image.FromFile似乎是导致错误的原因。在下面的问题中,它是一个已损坏的图像文件或文件句柄不足,image.FromStream()做得更好。值得一试,因为您已经打开了流:
我试过了,我可以重现你的问题。它肯定是内存不足,与“似乎是”完全不同,内存使用量增加到4 GB左右,然后出现错误。控制台输出只是为了查看那里发生了什么 图像对象似乎不是保存数据的最佳方式 我试过这个,得到了很多文件。也许您可以更改代码以满足您的需要:
String[] allfiles = Directory.GetFiles(imagePath, "*.*", SearchOption.AllDirectories);
//List<Image> allImages = new List<Image>();
List<Byte[]> allImagesBytes = new List<Byte[]>();
foreach (string file in allfiles)
{
using (FileStream stream = new FileStream(file, FileMode.Open, FileAccess.Read))
{
if (IsImage(stream))
{
Console.Clear();
Console.Write(allImagesBytes.Count());
//allImages.Add(Image.FromStream(stream));
//allImages.Add(Image.FromFile(file));
allImagesBytes.Add(File.ReadAllBytes(file));
}
}
}
String[]allfiles=Directory.GetFiles(imagePath,“**”,SearchOption.AllDirectories);
//列表所有图像=新列表();
List ALIMAGESBYTES=新列表();
foreach(所有文件中的字符串文件)
{
使用(FileStream stream=newfilestream(file,FileMode.Open,FileAccess.Read))
{
if(IsImage(流))
{
Console.Clear();
Write(allImagesBytes.Count());
//allImages.Add(Image.FromStream(stream));
//allImages.Add(Image.FromFile(file));
allImagesBytes.Add(File.ReadAllBytes(File));
}
}
}
您是否对其进行了分析以查看占用内存的内容?不,我不确定这是什么,我怎么看?分析程序是一种工具,它在程序运行时查看程序,并告诉您正在使用哪些资源以及在何处使用。我不使用C#,所以我不能推荐一个,但是谷歌搜索应该会显示一些例子。如果您使用的是IDE,它甚至可能有一个内置的。嗯,好吧,我会查看一个探查器图像
实现IDisposable
,您无处处理图像资源。它甚至没有走那么远,它会在allImages上抛出异常。Add(Image.FromFile(file));在一个小文件抛出一次后仍然会出现内存不足异常,如:“allImages.Add(Image.FromStream(stream));”?,这给了我一个System.Runtime.InteropServices.externalexception IsImage函数是什么样子的?在图像中重新使用流之前,您可能必须将流重置为位置0。FromStreamhold on我会将其添加到问题中谢谢,问题是转换